diff options
| author | Florian Fischer <florian.fl.fischer@fau.de> | 2020-05-06 16:56:32 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fl.fischer@fau.de> | 2020-06-02 11:18:47 +0200 |
| commit | 8174a918ea3b7cb216bf7ea98cfdc10661b5c37d (patch) | |
| tree | 0747ec3ccb9f8d7eeccfac35977fc17855ca3bbb /src | |
| parent | 8f52e8fc02dd235582f5961941bcd564e9a681cd (diff) | |
| download | allocbench-8174a918ea3b7cb216bf7ea98cfdc10661b5c37d.tar.gz allocbench-8174a918ea3b7cb216bf7ea98cfdc10661b5c37d.zip | |
make the whole project more python idiomatic
* rename src directory to allocbench
* make global variable names UPPERCASE
* format a lot of code using yapf
* use lowercase ld_preload and ld_library_path as Allocator members
* name expected Errors 'err' and don't raise a new Exception
* disable some pylint messages
Diffstat (limited to 'src')
189 files changed, 0 insertions, 35942 deletions
diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index caceb19..0000000 --- a/src/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -OPTFLAGS ?= -O0 -g - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -MEMSIZE_KB=$(shell free -t | tail -1 | tr -s ' ' | cut -d ' ' -f 2) -MEMSIZE="$(MEMSIZE_KB) * 1024l" - -TOOLS = print_status_on_exit.so exec sig_handlers.so -ALLOCS = bumpptr_alloc.so align_to_cl.so -TARGETS = $(addprefix $(OBJDIR)/allocators/,$(ALLOCS)) $(addprefix $(OBJDIR)/,$(TOOLS)) - -.PHONY: all clean - -all: $(TARGETS) - -$(OBJDIR)/allocators/bumpptr_alloc.so: bumpptr_alloc.c malloc.c Makefile - @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - $(CC) $(LDFLAGS) -shared -DMEMSIZE=$(MEMSIZE) $(CFLAGS) -o $@ bumpptr_alloc.c malloc.c - -$(OBJDIR)/allocators/align_to_cl.so: align_to_cl.c Makefile - @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - $(CC) $(LDFLAGS) -shared $(CFLAGS) -o $@ $< -ldl - -$(OBJDIR)/print_status_on_exit.so: print_status_on_exit.c Makefile - @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - $(CC) $(LDFLAGS) -shared $(CFLAGS) -o $@ $< - -$(OBJDIR)/sig_handlers.so: sig_handlers.c Makefile - @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - $(CC) $(LDFLAGS) -shared $(CFLAGS) -o $@ $< - -$(OBJDIR)/exec: exec.c Makefile - @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -clean: - rm -rf $(OBJDIR) diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index d989a60..0000000 --- a/src/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""A framework linking allocators to applications""" - -__author__ = "Florian Fischer" -__copyright__ = "Copyright 2018-2019 Florian Fischer" -__license__ = "GPL" -__maintainer__ = __author__ -__email__ = "florian.fl.fischer@fau.de" -__description__ = "A framework linking allocators to applications" diff --git a/src/align_to_cl.c b/src/align_to_cl.c deleted file mode 100644 index e54f065..0000000 --- a/src/align_to_cl.c +++ /dev/null @@ -1,240 +0,0 @@ -/* -Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> - -This file is part of allocbench. - -allocbench is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -allocbench is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with allocbench. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define _GNU_SOURCE -#include <dlfcn.h> -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define CACHE_LINE 64 - -static char tmpbuff[4096]; -static unsigned long tmppos = 0; -static unsigned long tmpallocs = 0; - -/*========================================================= - * intercepted functions - */ - -static void* (*next_malloc)(size_t size); -static void (*next_free)(void* ptr); -static void* (*next_calloc)(size_t nmemb, size_t size); -static void* (*next_realloc)(void* ptr, size_t size); -static void* (*next_memalign)(size_t alignment, size_t size); -static int (*next_posix_memalign)(void** memptr, size_t alignment, size_t size); -static void* (*next_valloc)(size_t size); -static void* (*next_pvalloc)(size_t size); -static void* (*next_aligned_alloc)(size_t alignment, size_t size); -static int (*next_malloc_stats)(); - -static void __attribute__((constructor)) -init() -{ - next_malloc = dlsym(RTLD_NEXT, "malloc"); - next_free = dlsym(RTLD_NEXT, "free"); - next_calloc = dlsym(RTLD_NEXT, "calloc"); - next_realloc = dlsym(RTLD_NEXT, "realloc"); - next_memalign = dlsym(RTLD_NEXT, "memalign"); - next_posix_memalign = dlsym(RTLD_NEXT, "posix_memalign"); - next_valloc = dlsym(RTLD_NEXT, "valloc"); - next_pvalloc = dlsym(RTLD_NEXT, "pvalloc"); - next_aligned_alloc = dlsym(RTLD_NEXT, "aligned_alloc"); - next_malloc_stats = dlsym(RTLD_NEXT, "malloc_stats"); - - if (!next_malloc || !next_free || !next_calloc || !next_realloc || - !next_memalign) { - fprintf(stderr, "Can't load core functions with `dlsym`: %s\n", dlerror()); - exit(1); - } - if (!next_posix_memalign) - fprintf(stderr, "Can't load posix_memalign with `dlsym`: %s\n", dlerror()); - if (!next_valloc) - fprintf(stderr, "Can't load valloc with `dlsym`: %s\n", dlerror()); - if (!next_pvalloc) - fprintf(stderr, "Can't load pvalloc with `dlsym`: %s\n", dlerror()); - if (!next_aligned_alloc) - fprintf(stderr, "Can't load aligned_alloc with `dlsym`: %s\n", dlerror()); - if (!next_malloc_stats) - fprintf(stderr, "Can't load malloc_stats with `dlsym`: %s\n", dlerror()); -} - -static void align_up_size(size_t* size) -{ - size_t s = *size; - size_t a = (s + CACHE_LINE + 1) & ~(CACHE_LINE - 1); - *size = a; -} - -void* -malloc(size_t size) -{ - static int initializing = 0; - - if (next_malloc == NULL) { - if (!initializing) { - initializing = 1; - init(); - initializing = 0; - - } else { - void* retptr = tmpbuff + tmppos; - tmppos += size; - ++tmpallocs; - - if (tmppos < sizeof(tmpbuff)) { - return retptr; - } else { - fprintf(stderr, "%d in %d allocs\n", tmppos, tmpallocs); - fprintf(stderr, - "jcheck: too much memory requested during initialisation - " - "increase tmpbuff size\n"); - exit(1); - } - } - } - - align_up_size(&size); - void* ptr = next_malloc(size); - return ptr; -} - -void -free(void* ptr) -{ - // something wrong if we call free before one of the allocators! - if (next_malloc == NULL) - init(); - if (!(ptr >= (void*)tmpbuff && ptr <= (void*)(tmpbuff + tmppos))) { - next_free(ptr); - } -} - -void* -realloc(void* ptr, size_t size) -{ - if (next_realloc == NULL) { - void* nptr = malloc(size); - if (nptr && ptr) { - memmove(nptr, ptr, size); - free(ptr); - } - return nptr; - } - - align_up_size(&size); - void* nptr = next_realloc(ptr, size); - return nptr; -} - -void* -calloc(size_t nmemb, size_t size) -{ - if (next_calloc == NULL) { - void* ptr = malloc(nmemb * size); - if (ptr) - memset(ptr, 0, nmemb * size); - return ptr; - } - - align_up_size(&size); - void* ptr = next_calloc(nmemb, size); - return ptr; -} - -void* -memalign(size_t alignment, size_t size) -{ - if (next_memalign == NULL) { - fprintf(stderr, "called memalign before or during init\n"); - exit(1); - } - - align_up_size(&size); - void* ptr = next_memalign(alignment, size); - return ptr; -} - -int -posix_memalign(void** memptr, size_t alignment, size_t size) -{ - if (next_posix_memalign == NULL) { - fprintf(stderr, "called posix_memalign before or during init\n"); - exit(1); - } - - align_up_size(&size); - int ret = next_posix_memalign(memptr, alignment, size); - return ret; -} - -void* -valloc(size_t size) -{ - if (next_valloc == NULL) { - fprintf(stderr, "called valloc before or during init"); - exit(1); - } - - align_up_size(&size); - void* ptr = next_valloc(size); - return ptr; -} - -void* -pvalloc(size_t size) -{ - if (next_pvalloc == NULL) { - fprintf(stderr, "called pvalloc before or during init\n"); - exit(1); - } - - align_up_size(&size); - void* ptr = next_pvalloc(size); - return ptr; -} - -void* -aligned_alloc(size_t alignment, size_t size) -{ - if (next_aligned_alloc == NULL) { - fprintf(stderr, "called aligned_alloc before or during init\n"); - exit(1); - } - - align_up_size(&size); - void* ptr = next_aligned_alloc(alignment, size); - return ptr; -} - -int -malloc_stats() -{ - if (next_malloc_stats == NULL) { - fprintf(stderr, "called malloc_stats before or during init\n"); - exit(1); - } - - fprintf(stderr, "align_to_cl by muhq\n"); - return next_malloc_stats(); -} diff --git a/src/allocator.py b/src/allocator.py deleted file mode 100644 index e14dfa7..0000000 --- a/src/allocator.py +++ /dev/null @@ -1,285 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Alloactor related class definitions and helpers""" - -from datetime import datetime -import fnmatch -import inspect -import importlib -import os -from pathlib import Path -import shutil -from subprocess import CalledProcessError -import sys - -from src.artifact import ArchiveArtifact, GitArtifact -import src.globalvars -from src.util import print_status, print_debug, print_error, print_info2, run_cmd - -LIBRARY_PATH = "" -for line in run_cmd(["ldconfig", "-v", "-N"], - capture=True).stdout.splitlines(): - - if not line.startswith('\t'): - LIBRARY_PATH += line - -BUILDDIR = Path(src.globalvars.allocbuilddir) -SRCDIR = BUILDDIR / "src" -ALLOCDEFDIR = Path('src/allocators') - -SRCDIR.mkdir(parents=True, exist_ok=True) - - -class Allocator: - """Allocator base class - - An Allocator can contain an Artifact which provides the allocator sources, - patches, and instructions to build the allocator. - Allocator.build will compile the allocator and produce a for allocbench usable - allocator dict""" - allowed_attributes = [ - "binary_suffix", "cmd_prefix", "LD_PRELOAD", "LD_LIBRARY_PATH", - "color", "sources", "version", "patches", "prepare_cmds", "build_cmds" - ] - - binary_suffix = None - cmd_prefix = None - LD_PRELOAD = None - LD_LIBRARY_PATH = None - color = None - sources = None - version = None - patches = [] - prepare_cmds = [] - build_cmds = [] - - def __init__(self, name, **kwargs): - self.class_file = Path(inspect.getfile(self.__class__)) - self.name = name - self.srcdir = SRCDIR / self.name - self.dir = BUILDDIR / self.name - self.patchdir = Path(self.class_file.parent, self.class_file.stem) - - # Update attributes - for attr, value in kwargs.items(): - setattr(self, attr, value) - - def prepare(self): - """Prepare the allocators sources""" - if not self.sources and self.srcdir.exists(): - return - - print_status("Preparing", self.name, "...") - if isinstance(self.sources, GitArtifact): - self.sources.provide(self.version, self.srcdir) - elif isinstance(self.sources, ArchiveArtifact): - self.sources.provide(self.srcdir) - - if self.patches: - cwd = self.srcdir - - print_status(f"Patching {self.name} ...") - for patch in self.patches: - with open(patch.format(patchdir=self.patchdir), - "r") as patch_file: - patch_content = patch_file.read() - - # check if patch is already applied - not_patched = run_cmd( - ["patch", "-R", "-p0", "-s", "-f", "--dry-run", "--verbose"], - cwd=cwd, - input=patch_content, - check=False).returncode - if not_patched: - try: - run_cmd(["patch", "-p0", "--verbose"], cwd=cwd, input=patch_content) - except CalledProcessError as e: - print_debug(e.stderr, file=sys.stderr) - print_error(f"Patching of {self.name} failed.") - raise e - - if self.prepare_cmds: - print_status(f"Run prepare commands {self.name} ...") - for cmd in self.prepare_cmds: - try: - run_cmd(cmd, shell=True, cwd=self.srcdir) - except CalledProcessError as e: - print_debug(e.stderr, file=sys.stderr) - print_error(f"Prepare {self.name} failed") - raise e - - def build(self): - """Build the allocator if needed and produce an allocator dict""" - build_needed = not self.dir.is_dir() - buildtimestamp_path = self.dir / ".buildtime" - - if not build_needed: - print_info2("Old build found. Comparing build time with mtime") - - with open(buildtimestamp_path, "r") as buildtimestamp_file: - timestamp = datetime.fromtimestamp( - float(buildtimestamp_file.read())) - - modtime = os.stat(self.class_file).st_mtime - modtime = datetime.fromtimestamp(modtime) - - build_needed = timestamp < modtime - - print_debug("Time of last build:", timestamp.isoformat()) - print_debug("Last modification of allocators file:", - modtime.isoformat()) - print_info2("" if build_needed else "No " + "build needed") - - if build_needed: - self.prepare() - print_status("Building", self.name, "...") - - for cmd in self.build_cmds: - cmd = cmd.format(dir=self.dir, srcdir=self.srcdir) - - try: - run_cmd(cmd, cwd=BUILDDIR, shell=True) - except CalledProcessError as e: - print_debug(e.stderr, file=sys.stderr) - print_error(f"Builing {self.name} failed") - shutil.rmtree(self.dir, ignore_errors=True) - raise e - - with open(buildtimestamp_path, "w") as buildtimestamp_file: - print_info2("Save build time to:", buildtimestamp_path) - buildtimestamp_file.write(str(datetime.now().timestamp())) - - print_info2("Create allocator dictionary") - res_dict = { - "cmd_prefix": self.cmd_prefix or "", - "binary_suffix": self.binary_suffix or "", - "LD_PRELOAD": self.LD_PRELOAD or "", - "LD_LIBRARY_PATH": self.LD_LIBRARY_PATH or "", - "color": self.color - } - - for attr in ["LD_PRELOAD", "LD_LIBRARY_PATH", "cmd_prefix"]: - value = getattr(self, attr, "") or "" - if value != "": - value = value.format(dir=self.dir, srcdir=self.srcdir) - res_dict[attr] = value - - print_debug("Resulting dictionary:", res_dict) - return res_dict - -def collect_installed_allocators(): - """Collect allocators using installed system libraries""" - - # TODO: add more allocators - maybe_allocators = ["tcmalloc", "jemalloc", "hoard"] - - allocators = { - "libc": { - "cmd_prefix": "", - "binary_suffix": "", - "LD_PRELOAD": "", - "LD_LIBRARY_PATH": "", - "color": "C1" - } - } - - for alloc in maybe_allocators: - try: - path = run_cmd(f'whereis lib{alloc} | cut -d":" -f2', - shell=True, - capture=True).stdout.strip() - except CalledProcessError: - continue - - if path != "": - allocators[alloc] = { - "cmd_prefix": "", - "binary_suffix": "", - "LD_PRELOAD": path, - "LD_LIBRARY_PATH": "", - "color": None, - } - - return allocators - -def collect_available_allocators(): - """Collect all allocator definitions shipped with allocbench""" - - available_allocators = {} - - for alloc_def_path in Path(ALLOCDEFDIR).glob('*.py'): - alloc_module_name = '.'.join(alloc_def_path.parts[:-1] + (alloc_def_path.stem,)) - module = importlib.import_module(alloc_module_name) - for name, obj in module.__dict__.items(): - if issubclass(obj.__class__, src.allocator.Allocator): - available_allocators[name] = obj - - return available_allocators - -def read_allocators_collection_file(alloc_path): - """Read and evaluate a python file looking for an exported dict called allocators""" - - exec_globals = {"__file__": alloc_path} - with open(alloc_path, "r") as alloc_file: - exec(compile(alloc_file.read(), alloc_path, 'exec'), exec_globals) - - if "allocators" in exec_globals: - return {a.name: a.build() for a in exec_globals["allocators"]} - - print_error("No global dictionary 'allocators' in", alloc_path) - return {} - - -def collect_allocators(allocators): - """Collect allocators to benchmark - - If allocators is None we use either the allocators exported in the default - allocators file at build/allocators/allocators.py or the ones installed. - - Otherwise allocators is interpreted as a list of names or files. If an entry in - allocators is a file it is handled as a allocator collection file exporting - a allocators variable. If the entry is no file it is interpreted as an allocator - name and is searched for in our allocator definitions located at src/allocators. - """ - - # Default allocators definition file - default_allocators_file = "build/allocators/allocators.py" - - if allocators is None and os.path.isfile(default_allocators_file): - return read_allocators_collection_file(default_allocators_file) - - ret = {} - for name in allocators: - if name == "installed": - print_status("Using system-wide installed allocators ...") - ret.update(collect_installed_allocators()) - # file exists -> interpret as python file with a global variable allocators - elif os.path.isfile(name): - print_status("Sourcing allocators definitions at", name, "...") - ret.update(read_allocators_collection_file(name)) - - # interpret name as allocator name or wildcard - else: - available_allocators = collect_available_allocators() - matched_allocators = fnmatch.filter(available_allocators.keys(), name) - if matched_allocators: - ret.update({a: available_allocators[a].build() for a in matched_allocators}) - else: - print_error( - name, - "is neither a python file or a known allocator definition.") - return ret diff --git a/src/allocators/BA_allocators.py b/src/allocators/BA_allocators.py deleted file mode 100644 index 9c11873..0000000 --- a/src/allocators/BA_allocators.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Collection containing all allocators used in Florian's BA thesis""" - -from src.allocators.glibc import glibc, glibc_notc -from src.allocators.tcmalloc import tcmalloc -from src.allocators.jemalloc import jemalloc -from src.allocators.hoard import hoard - -allocators = [glibc, glibc_notc, tcmalloc, jemalloc, hoard] diff --git a/src/allocators/__init__.py b/src/allocators/__init__.py deleted file mode 100644 index d5c6419..0000000 --- a/src/allocators/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""allocbench allocator definitions""" diff --git a/src/allocators/bumpptr.py b/src/allocators/bumpptr.py deleted file mode 100644 index 9165352..0000000 --- a/src/allocators/bumpptr.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Bumpptr allocator - -The bumpptr allocator makes the biggest possible tradeoff between speed and -memory in speeds favor. Memory is mmapped per thread and never freed. -See src/bumpptr.c for the actual implementation. -""" - -import os -from src.allocator import Allocator, BUILDDIR - -bumpptr = Allocator("bumpptr", - LD_PRELOAD=os.path.join(BUILDDIR, "bumpptr_alloc.so"), - color="xkcd:black") diff --git a/src/allocators/chattymalloc.py b/src/allocators/chattymalloc.py deleted file mode 100644 index ff4a3ba..0000000 --- a/src/allocators/chattymalloc.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""chattymalloc allocator - -This shared library is not a functional allocator. It is used to trace -the allocator usage and the executed program. It overrides the malloc API -and saves each call and its result to a memory mapped output file. -""" - -import os - -from src.artifact import GitArtifact -from src.allocator import Allocator - -VERSION = "1a09b144eb18919014ecf86da3442344b0eaa5b2" - -class Chattymalloc(Allocator): - """Chattymalloc definition for allocbench""" - - sources = GitArtifact("chattymalloc", - "https://github.com/fischerling/chattymalloc") - - def __init__(self, name, **kwargs): - - configuration = "--buildtype=release " - for option, value in kwargs.get("options", {}).items(): - configuration += f"-D{option}={value} " - - self.build_cmds = [ - f"meson {{srcdir}} {{dir}} {configuration}", "ninja -C {dir}" - ] - - self.LD_PRELOAD = "{dir}/libchattymalloc.so" - self.cmd_prefix="env CHATTYMALLOC_FILE={{result_dir}}/{{perm}}.trace" - super().__init__(name, **kwargs) - - -chattymalloc = Chattymalloc("chattymalloc", version=VERSION) diff --git a/src/allocators/glibc.py b/src/allocators/glibc.py deleted file mode 100644 index 5d2814d..0000000 --- a/src/allocators/glibc.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Glibc definitions""" - -from multiprocessing import cpu_count - -from src.allocator import Allocator, LIBRARY_PATH -from src.artifact import GitArtifact - - -class Glibc(Allocator): - """Glibc definition for allocbench - - Glibcs are loaded using their own supplied loader""" - - sources = GitArtifact("glibc", "git://sourceware.org/git/glibc.git") - - def __init__(self, name, **kwargs): - configure_args = "" - if "configure_args" in kwargs: - configure_args = kwargs["configure_args"] - del kwargs["configure_args"] - - self.build_cmds = [ - "mkdir -p glibc-build", - "cd glibc-build; {srcdir}/configure --prefix={dir} " + - configure_args, "cd glibc-build; make", - f"cd glibc-build; make -l {cpu_count()} install" - ] - - self.cmd_prefix = "{dir}/lib/ld-linux-x86-64.so.2 --library-path {dir}/lib:" + LIBRARY_PATH - - super().__init__(name, **kwargs) - - -glibc = Glibc("glibc", version="glibc-2.29", color="xkcd:red") - -glibc_notc = Glibc("glibc-noThreadCache", - configure_args="--disable-experimental-malloc", - version="glibc-2.29", - color="xkcd:maroon") - -glibc_nofs = Glibc( - "glibc-noFalsesharing", - patches=["{patchdir}/glibc_2.29_no_passive_falsesharing.patch"], - version="glibc-2.29", - color="xkcd:pink") - -glibc_nofs_fancy = Glibc( - "glibc-noFalsesharingClever", - patches=["{patchdir}/glibc_2.29_no_passive_falsesharing_fancy.patch"], - version="glibc-2.29", - color="xkcd:orange") diff --git a/src/allocators/glibc/glibc_2.29_no_passive_falsesharing.patch b/src/allocators/glibc/glibc_2.29_no_passive_falsesharing.patch deleted file mode 100644 index becbfda..0000000 --- a/src/allocators/glibc/glibc_2.29_no_passive_falsesharing.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git malloc/malloc.c malloc/malloc.c -index 0abd653be2..eaefd3bd7c 100644 ---- malloc/malloc.c -+++ malloc/malloc.c -@@ -4194,6 +4194,9 @@ _int_free (mstate av, mchunkptr p, int have_lock) - - #if USE_TCACHE - { -+ /* Check if chunk is from our own arena. */ -+ if (av == thread_arena) -+ { - size_t tc_idx = csize2tidx (size); - if (tcache != NULL && tc_idx < mp_.tcache_bins) - { -@@ -4223,6 +4226,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) - return; - } - } -+ } - } - #endif - -@@ -4997,6 +5001,7 @@ __malloc_stats (void) - memset (&mi, 0, sizeof (mi)); - __libc_lock_lock (ar_ptr->mutex); - int_mallinfo (ar_ptr, &mi); -+ fprintf (stderr, "false sharing path by muhq\n"); - fprintf (stderr, "Arena %d:\n", i); - fprintf (stderr, "system bytes = %10u\n", (unsigned int) mi.arena); - fprintf (stderr, "in use bytes = %10u\n", (unsigned int) mi.uordblks); diff --git a/src/allocators/glibc/glibc_2.29_no_passive_falsesharing_fancy.patch b/src/allocators/glibc/glibc_2.29_no_passive_falsesharing_fancy.patch deleted file mode 100644 index 480d072..0000000 --- a/src/allocators/glibc/glibc_2.29_no_passive_falsesharing_fancy.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git malloc/malloc.c malloc/malloc.c -index 0abd653be2..71b2d433ba 100644 ---- malloc/malloc.c -+++ malloc/malloc.c -@@ -4194,6 +4194,12 @@ _int_free (mstate av, mchunkptr p, int have_lock) - - #if USE_TCACHE - { -+ /* Check if chunk is from our own arena or false sharing is not possible -+ because the chunk is cache line aligned and it's size is a multiple -+ of a cacheline */ -+ if (av == thread_arena -+ || (((size_t)p & 63) == 0 && ((size + 2*SIZE_SZ) % 64) == 0)) -+ { - size_t tc_idx = csize2tidx (size); - if (tcache != NULL && tc_idx < mp_.tcache_bins) - { -@@ -4223,6 +4229,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) - return; - } - } -+ } - } - #endif - -@@ -4997,6 +5004,7 @@ __malloc_stats (void) - memset (&mi, 0, sizeof (mi)); - __libc_lock_lock (ar_ptr->mutex); - int_mallinfo (ar_ptr, &mi); -+ fprintf (stderr, "fancy false sharing patch by muhq"); - fprintf (stderr, "Arena %d:\n", i); - fprintf (stderr, "system bytes = %10u\n", (unsigned int) mi.arena); - fprintf (stderr, "in use bytes = %10u\n", (unsigned int) mi.uordblks); diff --git a/src/allocators/hoard.py b/src/allocators/hoard.py deleted file mode 100644 index 5d0c2ce..0000000 --- a/src/allocators/hoard.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Hoard allocator definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Hoard(Allocator): - """Hoard allocator""" - - sources = GitArtifact("Hoard", "https://github.com/emeryberger/Hoard.git") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libhoard.so" - self.build_cmds = [ - "cd {srcdir}/src; make", "mkdir -p {dir}", - "ln -f -s {srcdir}/src/libhoard.so {dir}/libhoard.so" - ] - self.requirements = ["clang"] - - super().__init__(name, **kwargs) - - -hoard = Hoard("Hoard", - version="aa6d31700d5368a9f5ede3d62731247c8d9f0ebb", - color="xkcd:brown") diff --git a/src/allocators/jemalloc.py b/src/allocators/jemalloc.py deleted file mode 100644 index ab2528b..0000000 --- a/src/allocators/jemalloc.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""jemalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Jemalloc(Allocator): - """jemalloc allocator""" - - sources = GitArtifact("jemalloc", - "https://github.com/jemalloc/jemalloc.git") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libjemalloc.so" - self.prepare_cmds = ["./autogen.sh"] - self.build_cmds = [ - "cd {srcdir}; ./configure --prefix={dir}", "cd {srcdir}; make -j4", - "mkdir -p {dir}", - "ln -f -s {srcdir}/lib/libjemalloc.so {dir}/libjemalloc.so" - ] - - super().__init__(name, **kwargs) - - -jemalloc = Jemalloc("jemalloc", version="5.1.0", color="xkcd:yellow") diff --git a/src/allocators/llalloc.py b/src/allocators/llalloc.py deleted file mode 100644 index d3c5288..0000000 --- a/src/allocators/llalloc.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Lockless allocator definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import ArchiveArtifact - - -class LocklessAllocator(Allocator): - """Lockless allocator""" - def __init__(self, name, **kwargs): - - self.sources = ArchiveArtifact( - "llalloc", - "https://locklessinc.com/downloads/lockless_allocator_src.tgz", - "tar", "c6cb5a57882fa4775b5227a322333a6126b61f7c") - - self.build_cmds = [ - "cd {srcdir}/lockless_allocator; make", "mkdir -p {dir}", - "ln -f -s {srcdir}/lockless_allocator/libllalloc.so.1.3 {dir}/libllalloc.so" - ] - - self.LD_PRELOAD = "{dir}/libllalloc.so" - - super().__init__(name, **kwargs) - - -llalloc = LocklessAllocator("llalloc", color="purple") diff --git a/src/allocators/malt.py b/src/allocators/malt.py deleted file mode 100644 index 8613145..0000000 --- a/src/allocators/malt.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""malt allocator definition - -Malt is a malloc tracker and used to capture and analyse the allocation profile -of a program. See https://github.com/memtt/malt for more details -""" - -from src.allocator import Allocator - -# result_dir and perm are substituted during Benchmark.run -malt = Allocator( - "malt", - cmd_prefix="malt -q -o output:name={{result_dir}}/malt.{{perm}}.%3") diff --git a/src/allocators/mesh.py b/src/allocators/mesh.py deleted file mode 100644 index 4d99f4d..0000000 --- a/src/allocators/mesh.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Mesh definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Mesh(Allocator): - """Mesh allocator""" - - sources = GitArtifact("Mesh", "https://github.com/plasma-umass/Mesh") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libmesh.so" - self.build_cmds = [ - "cd {srcdir}; ./configure", "cd {srcdir}; make -j 4", - "mkdir -p {dir}", "ln -f -s {srcdir}/libmesh.so {dir}/libmesh.so" - ] - - super().__init__(name, **kwargs) - - -mesh = Mesh("Mesh", - version="4a1012cee990cb98cc1ea0294a836f467b29be02", - color="xkcd:mint") diff --git a/src/allocators/mimalloc.py b/src/allocators/mimalloc.py deleted file mode 100644 index 6801191..0000000 --- a/src/allocators/mimalloc.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""mimalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Mimalloc(Allocator): - """mimalloc allocator""" - - sources = GitArtifact("mimalloc", "https://github.com/microsoft/mimalloc") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libmimalloc.so" - self.build_cmds = [ - "mkdir -p {dir}", "cd {dir}; cmake {srcdir}", "cd {dir}; make" - ] - self.requirements = ["cmake"] - - super().__init__(name, **kwargs) - - -mimalloc = Mimalloc("mimalloc", version="v1.6.0") diff --git a/src/allocators/no_falsesharing.py b/src/allocators/no_falsesharing.py deleted file mode 100644 index 77310b3..0000000 --- a/src/allocators/no_falsesharing.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Collection containing all no falsesahring patches""" - -from src.allocators.tcmalloc import tcmalloc_gperftools, tcmalloc_gperftools_nofs -from src.allocators.glibc import glibc, glibc_nofs, glibc_nofs_fancy - -allocators = [ - glibc, glibc_nofs, glibc_nofs_fancy, tcmalloc_gperftools, - tcmalloc_gperftools_nofs -] diff --git a/src/allocators/paper.py b/src/allocators/paper.py deleted file mode 100644 index 3f36be9..0000000 --- a/src/allocators/paper.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Collection containing all available allocators""" - -from src.allocators.glibc import glibc -from src.allocators.tcmalloc import tcmalloc, tcmalloc_align, tcmalloc_gperftools, tcmalloc_gperftools_align -from src.allocators.jemalloc import jemalloc -from src.allocators.scalloc import scalloc -from src.allocators.llalloc import llalloc -from src.allocators.tbbmalloc import tbbmalloc -from src.allocators.mimalloc import mimalloc -from src.allocators.bumpptr import bumpptr -from src.allocators.speedymalloc import speedymalloc - -allocators = [ - glibc, tcmalloc, tcmalloc_align, tcmalloc_gperftools, - tcmalloc_gperftools_align, jemalloc, llalloc, mimalloc, bumpptr, - speedymalloc -] diff --git a/src/allocators/rpmalloc.py b/src/allocators/rpmalloc.py deleted file mode 100644 index c27f244..0000000 --- a/src/allocators/rpmalloc.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""rpmalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Rpmalloc(Allocator): - """rpmalloc allocator""" - - sources = GitArtifact("rpmalloc", "https://github.com/mjansson/rpmalloc") - - def __init__(self, name, **kwargs): - - self.LD_PRELOAD = "{dir}/librpmalloc.so" - self.build_cmds = [ - "cd {srcdir}; ./configure.py", "cd {srcdir}; ninja", - "mkdir -p {dir}", - 'ln -f -s $(find {srcdir}/bin -path "*release*librpmalloc.so") {dir}/librpmalloc.so' - ] - - super().__init__(name, **kwargs) - - -rpmalloc = Rpmalloc("rpmalloc", color="xkcd:chestnut", version="1.4.0") diff --git a/src/allocators/scalloc.py b/src/allocators/scalloc.py deleted file mode 100644 index c071f22..0000000 --- a/src/allocators/scalloc.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Scalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Scalloc(Allocator): - """Scalloc allocator""" - - sources = GitArtifact("scalloc", - "https://github.com/cksystemsgroup/scalloc") - - def __init__(self, name, **kwargs): - self.prepare_cmds = [ - "tools/make_deps.sh", "build/gyp/gyp --depth=. scalloc.gyp" - ] - - self.build_cmds = [ - "cd {srcdir}; BUILDTYPE=Release make", "mkdir -p {dir}" - ] - - self.LD_PRELOAD = "{srcdir}/out/Release/lib.target/libscalloc.so" - - self.patches = ["{patchdir}/scalloc_fix_log.patch"] - - super().__init__(name, **kwargs) - - def build(self): - with open("/proc/sys/vm/overcommit_memory", "r") as f: - if f.read()[0] != "1": - raise AssertionError("""\ -vm.overcommit_memory not set -Scalloc needs permission to overcommit_memory. -sysctl vm.overcommit_memory=1 -""") - return super().build() - - -scalloc = Scalloc("scalloc", color="xkcd:magenta", version="v1.0.0") diff --git a/src/allocators/scalloc/scalloc_fix_log.patch b/src/allocators/scalloc/scalloc_fix_log.patch deleted file mode 100644 index 9d4a7d8..0000000 --- a/src/allocators/scalloc/scalloc_fix_log.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git src/log.h src/log.h -index 3edc36d..e1d181c 100644 ---- src/log.h -+++ src/log.h -@@ -46,13 +46,13 @@ inline void LogPrintf( - - snprintf(line_buffer, sizeof(line_buffer), "%d", line); - // Start with "__FILENAME__:__LINE__ ". -- strncat(buffer, file, strlen(file)); -+ strncat(buffer, file, rest); - rest -= strlen(file); -- strncat(buffer, ":", 1); -+ strncat(buffer, ":", rest); - rest -= 1; -- strncat(buffer, line_buffer, strlen(line_buffer)); -+ strncat(buffer, line_buffer, rest); - rest -= strlen(line_buffer); -- strncat(buffer, " ", 1); -+ strncat(buffer, " ", rest); - rest -= 1; - - // Sanity check. -@@ -69,10 +69,10 @@ inline void LogPrintf( - // For copying the suffix we need actual rest value again. - strncpy(rest_start + (rest - strlen(truncate_suffix)), - truncate_suffix, -- strlen(truncate_suffix)); -+ rest); - } - -- strncat(buffer, "\n", 1); -+ strncat(buffer, "\n", rest); - - // Sanity check. - if (buffer[kLogLen-1] != 0) { diff --git a/src/allocators/snmalloc.py b/src/allocators/snmalloc.py deleted file mode 100644 index 2c5dfa8..0000000 --- a/src/allocators/snmalloc.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Snmalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Snmalloc(Allocator): - """snmalloc allocator""" - - sources = GitArtifact("snmalloc", "https://github.com/microsoft/snmalloc") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libsnmallocshim.so" - self.build_cmds = [ - "mkdir -p {dir}", - "cd {dir}; cmake -G Ninja {srcdir} -DCMAKE_BUILD_TYPE=Release", - "cd {dir}; ninja" - ] - self.requirements = ["cmake", "ninja", "clang"] - - super().__init__(name, **kwargs) - - -snmalloc = Snmalloc("snmalloc", version="0.2") diff --git a/src/allocators/speedymalloc.py b/src/allocators/speedymalloc.py deleted file mode 100644 index 6fe202a..0000000 --- a/src/allocators/speedymalloc.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Speedymalloc - -Speedymalloc is a cached bump pointer allocator. -A bump pointer allocator makes the biggest possible tradeoff between speed and -memory in speeds favor. Memory is mmapped per thread and never freed. -""" - -from src.artifact import GitArtifact -from src.allocator import Allocator - -VERSION = "dd24b9d24c78c798df97ca5556ba248ccff97ca7" - - -class Speedymalloc(Allocator): - """Speedymalloc definition for allocbench""" - - sources = GitArtifact("speedymalloc", - "https://gitlab.cs.fau.de/flow/speedymalloc.git") - - def __init__(self, name, **kwargs): - - configuration = "--buildtype=release " - for option, value in kwargs.get("options", {}).items(): - configuration += f"-D{option}={value} " - - self.build_cmds = [ - f"meson {{srcdir}} {{dir}} {configuration}", "ninja -C {dir}" - ] - - self.LD_PRELOAD = "{dir}/libspeedymalloc.so" - super().__init__(name, **kwargs) - - -speedymalloc = Speedymalloc("speedymalloc", version=VERSION) - -speedymalloc_no_madv_free = Speedymalloc("speedymalloc_no_madv_free", - options={"madvise_free": "false"}, - version=VERSION) - -speedymalloc_no_madv_willneed = Speedymalloc( - "speedymalloc_no_madv_willneed", - options={"madvise_willneed": "false"}, - version=VERSION) - -speedymalloc_4095_sc_32 = Speedymalloc("speedymalloc_4095_sc_32", - options={ - "cache_bins": 4095, - "cache_bin_seperation": 32 - }, - version=VERSION) - -speedymalloc_4095_sc_128 = Speedymalloc("speedymalloc_4095_sc_128", - options={ - "cache_bins": 4095, - "cache_bin_seperation": 128 - }, - version=VERSION) - -speedymalloc_only_glab = Speedymalloc( - "speedymalloc_only_glab", - options={"max_local_allocation_buffer_size": 0}, - version=VERSION) - -speedymalloc_no_glab = Speedymalloc( - "speedymalloc_no_glab", - options={"max_local_allocation_buffer_size": -1}, - version=VERSION) - -# speedymalloc_rseq = Speedymalloc( - # "speedymalloc_rseq", - # version="e1549fa2a2833deba0ba53504a6c67ee31a0e42a") diff --git a/src/allocators/streamflow.py b/src/allocators/streamflow.py deleted file mode 100644 index 3b04a21..0000000 --- a/src/allocators/streamflow.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""Streamflow allocator definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class Streamflow(Allocator): - """Streamflow allocator""" - - sources = GitArtifact("streamflow", "https://github.com/scotts/streamflow") - - def __init__(self, name, **kwargs): - - self.LD_PRELOAD = "{dir}/libstreamflow.so" - self.build_cmds = [ - "cd {srcdir}; make", "mkdir -p {dir}", - "ln -f -s {srcdir}/libstreamflow.so {dir}/libstreamflow.so" - ] - - super().__init__(name, **kwargs) - - -streamflow = Streamflow("Streamflow", - version="8ac345c0f69ec9e7af02f3555c2c97eaa07a442e", - color="xkcd:light brown") diff --git a/src/allocators/supermalloc.py b/src/allocators/supermalloc.py deleted file mode 100644 index 32f9588..0000000 --- a/src/allocators/supermalloc.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""SuperMalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class SuperMalloc(Allocator): - """SuperMalloc allocator""" - - sources = GitArtifact("SuperMalloc", - "https://github.com/kuszmaul/SuperMalloc") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libsupermalloc.so" - self.build_cmds = [ - "cd {srcdir}/release; make", "mkdir -p {dir}", - "ln -f -s {srcdir}/release/lib/libsupermalloc.so {dir}/libsupermalloc.so" - ] - self.patches = ["{patchdir}/remove_faulty_aligned_alloc_test.patch"] - - super().__init__(name, **kwargs) - - -supermalloc = SuperMalloc("SuperMalloc", - color="xkcd:lime", - version="709663fb81ba091b0a78058869a644a272f4163d") diff --git a/src/allocators/supermalloc/remove_faulty_aligned_alloc_test.patch b/src/allocators/supermalloc/remove_faulty_aligned_alloc_test.patch deleted file mode 100644 index 074f758..0000000 --- a/src/allocators/supermalloc/remove_faulty_aligned_alloc_test.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git Makefile.include Makefile.include -index bb3cef3..09ee7eb 100644 ---- Makefile.include -+++ Makefile.include -@@ -37,7 +37,7 @@ default: tests - #lib: $(LIB)/libsupermalloc.so - #.PHONY: lib - --TESTS = aligned_alloc calloc posix_memalign $(UNITTESTS) test-malloc_test new-malloc-test malloc-test-fixed-work test22 cache-index madvise-small test38 test-no-overlaps #unit-timing -+TESTS = calloc posix_memalign $(UNITTESTS) test-malloc_test new-malloc-test malloc-test-fixed-work test22 cache-index madvise-small test38 test-no-overlaps #unit-timing - TESTS_IN_DIR = $(patsubst %, $(BLD)/%, $(TESTS)) - - LDFLAGS += -ldl diff --git a/src/allocators/tbbmalloc.py b/src/allocators/tbbmalloc.py deleted file mode 100644 index 6580939..0000000 --- a/src/allocators/tbbmalloc.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""tbbmalloc definition for allocbench""" - -from src.allocator import Allocator -from src.artifact import GitArtifact - - -class TBBMalloc(Allocator): - """tbbmalloc allocator""" - - sources = GitArtifact("tbb", "https://github.com/intel/tbb.git") - - def __init__(self, name, **kwargs): - self.LD_PRELOAD = "{dir}/libtbbmalloc.so" - self.build_cmds = [ - "cd {srcdir}; make tbbmalloc -j4", "mkdir -p {dir}", - 'ln -f -s $(find {srcdir} -executable -name "*libtbbmalloc_proxy.so*" | head -1) {dir}/libtbbmalloc.so' - ] - - super().__init__(name, **kwargs) - - -tbbmalloc = TBBMalloc("tbbmalloc", color="xkcd:green", version="2019_U8") diff --git a/src/allocators/tcmalloc.py b/src/allocators/tcmalloc.py deleted file mode 100644 index 7f67146..0000000 --- a/src/allocators/tcmalloc.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. -"""TCMalloc definition for allocbench""" - -from src.allocator import Allocator, BUILDDIR -from src.artifact import GitArtifact - - -class TCMalloc(Allocator): - """TCMalloc allocator""" - - sources = GitArtifact("tcmalloc", "https://github.com/google/tcmalloc.git") - - def __init__(self, name, **kwargs): - - self.LD_PRELOAD = "{dir}/libtcmalloc.so" - self.patches = ["{patchdir}/tcmalloc_bazel_build_so.patch"] - self.build_cmds = [ - "cd {srcdir}; bazel build tcmalloc/tcmalloc.so --compilation_mode opt", - "mkdir -p {dir}", - "cp -f {srcdir}/bazel-bin/tcmalloc/tcmalloc.so {dir}/libtcmalloc.so" - ] - - super().__init__(name, **kwargs) - - -tcmalloc = TCMalloc("TCMalloc", - color="xkcd:blue", - version="1676100265bd189df6b5513feac15f102542367e") - -tcmalloc_align = TCMalloc("TCMalloc-Aligned", - version="1676100265bd189df6b5513feac15f102542367e", - color="xkcd:light blue") - -tcmalloc_align.LD_PRELOAD = f"{BUILDDIR}/align_to_cl.so {tcmalloc_align.LD_PRELOAD}" - - -class TCMallocGperftools(Allocator): - """gperftools TCMalloc allocator""" - - sources = GitArtifact("gperftools", - "https://github.com/gperftools/gperftools.git") - - def __init__(self, name, **kwargs): - - self.LD_PRELOAD = "{dir}/lib/libtcmalloc.so" - self.prepare_cmds = ["./autogen.sh"] - self.build_cmds = [ - "cd {srcdir}; ./configure --prefix={dir}", - "cd {srcdir}; make install -j4" - ] - - super().__init__(name, **kwargs) - - -tcmalloc_gperftools = TCMallocGperftools("TCMalloc-gperftools", - color="xkcd:dark blue", - version="gperftools-2.7") - -tcmalloc_gperftools_nofs = TCMallocGperftools( - "TCMalloc-Gperftools-NoFalsesharing", - patches=["{patchdir}/tcmalloc_2.7_no_active_falsesharing.patch"], - version="gperftools-2.7", - color="xkcd:navy") - -tcmalloc_gperftools_align = TCMallocGperftools("TCMalloc-Gperftools-Aligned", - version="gperftools-2.7", - color="xkcd:navy blue") - -tcmalloc_gperftools_align.LD_PRELOAD = f"{BUILDDIR}/align_to_cl.so {tcmalloc_gperftools_align.LD_PRELOAD}" - -tcmalloc_gperftools_cacheline_exclusive = TCMallocGperftools( - "TCMalloc-Gperftools-Cacheline-Exclusive", - patches=["{patchdir}/tcmalloc_2.7_cacheline_exclusive.patch"], - version="gperftools-2.7", - color="xkcd:royal blue") diff --git a/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch b/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch deleted file mode 100644 index bdd63e3..0000000 --- a/src/allocators/tcmalloc/tcmalloc_2.7_cacheline_exclusive.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git src/common.cc src/common.cc -index 203afdf..9257518 100644 ---- src/common.cc -+++ src/common.cc -@@ -79,7 +79,7 @@ int AlignmentForSize(size_t size) { - if (size > kMaxSize) { - // Cap alignment at kPageSize for large sizes. - alignment = kPageSize; -- } else if (size >= 128) { -+ } else if (size >= 512) { - // Space wasted due to alignment is at most 1/8, i.e., 12.5%. - alignment = (1 << LgFloor(size)) / 8; - } else if (size >= kMinAlign) { -diff --git a/src/common.h b/src/common.h -index cb45315..4131a13 100644 ---- src/common.h -+++ src/common.h -@@ -61,7 +61,7 @@ typedef uintptr_t Length; - // waste due alignment of 25%. (eg malloc of 24 bytes will get 32 bytes) - static const size_t kMinAlign = 8; - #else --static const size_t kMinAlign = 16; -+static const size_t kMinAlign = 64; - #endif - - // Using large pages speeds up the execution at a cost of larger memory use. diff --git a/src/allocators/tcmalloc/tcmalloc_2.7_no_active_falsesharing.patch b/src/allocators/tcmalloc/tcmalloc_2.7_no_active_falsesharing.patch deleted file mode 100644 index a76a2f2..0000000 --- a/src/allocators/tcmalloc/tcmalloc_2.7_no_active_falsesharing.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git src/thread_cache.cc src/thread_cache.cc -index 6d2f832..2074f4a 100644 ---- src/thread_cache.cc -+++ src/thread_cache.cc -@@ -120,7 +120,11 @@ void* ThreadCache::FetchFromCentralCache(uint32 cl, int32_t byte_size, - ASSERT(list->empty()); - const int batch_size = Static::sizemap()->num_objects_to_move(cl); - -- const int num_to_move = min<int>(list->max_length(), batch_size); -+ int num_to_move = min<int>(list->max_length(), batch_size); -+ const int cache_line_parts = 64 / byte_size; -+ if (cache_line_parts > 0 && cache_line_parts > num_to_move) -+ num_to_move = cache_line_parts; -+ - void *start, *end; - int fetch_count = Static::central_cache()[cl].RemoveRange( - &start, &end, num_to_move); diff --git a/src/allocators/tcmalloc/tcmalloc_bazel_build_so.patch b/src/allocators/tcmalloc/tcmalloc_bazel_build_so.patch deleted file mode 100644 index cdd2840..0000000 --- a/src/allocators/tcmalloc/tcmalloc_bazel_build_so.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git tcmalloc/BUILD tcmalloc/BUILD -index 66d160e..25946af 100644 ---- tcmalloc/BUILD -+++ tcmalloc/BUILD -@@ -109,6 +109,17 @@ cc_library( - alwayslink = 1, - ) - -+# This library provides tcmalloc as shared object -+cc_binary( -+ name = "tcmalloc.so", -+ copts = TCMALLOC_DEFAULT_COPTS, -+ linkshared = 1, -+ linkstatic = 1, -+ deps = overlay_deps + tcmalloc_deps + [ -+ ":tcmalloc", -+ ] -+) -+ - # Provides tcmalloc always; use per-thread mode. - # - cc_library( diff --git a/src/analyse.py b/src/analyse.py deleted file mode 100755 index bd08c98..0000000 --- a/src/analyse.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Analyze benchmarks and allocators""" - -import importlib -import os -import traceback - -from src.util import find_cmd -from src.util import print_status, print_warn, print_error -from src.util import print_info2, print_debug - -ANALYZSE_ALLOC_NAME = None -ANALYZSE_ALLOC_DICT = None - - -def build_analyze_alloc(): - """Select and build available analysis allocator""" - global ANALYZSE_ALLOC_NAME - global ANALYZSE_ALLOC_DICT - if ANALYZSE_ALLOC_DICT is not None: - return - - if find_cmd("malt") is not None: - ANALYZSE_ALLOC_NAME = "malt" - else: - print_warn("malt not found. Using chattymalloc.") - ANALYZSE_ALLOC_NAME = "chattymalloc" - - analyze_alloc_module = importlib.import_module( - f"src.allocators.{ANALYZSE_ALLOC_NAME}") - - ANALYZSE_ALLOC_DICT = getattr(analyze_alloc_module, - ANALYZSE_ALLOC_NAME).build() - - -def analyze_bench(bench): - """Analyse a single benchmark""" - print_status("Analysing {} ...".format(bench)) - - # Create benchmark result directory - if not os.path.isdir(bench.result_dir): - print_info2("Creating benchmark result dir:", bench.result_dir) - os.makedirs(bench.result_dir, exist_ok=True) - - build_analyze_alloc() - - old_allocs = bench.allocators - old_measure_cmd = bench.measure_cmd - bench.measure_cmd = "" - bench.allocators = {ANALYZSE_ALLOC_NAME: ANALYZSE_ALLOC_DICT} - - try: - bench.run(runs=1) - except Exception: - print_debug(traceback.format_exc()) - print_error("Skipping analysis of", bench, "!") - - bench.measure_cmd = old_measure_cmd - - # Remove results for analyze_alloc - if ANALYZSE_ALLOC_NAME in bench.results: - del bench.results[ANALYZSE_ALLOC_NAME] - if "stats" in bench.results and ANALYZSE_ALLOC_NAME in bench.results[ - "stats"]: - del bench.results["stats"][ANALYZSE_ALLOC_NAME] - - # restore allocs - bench.allocators = old_allocs - - -def analyze_allocators(bench, allocators): - """Analyse a single benchmark for each allocator in allocators""" - # build analyzse allocator before globaly setting LD_PRELOAD - build_analyze_alloc() - - for name, alloc in allocators.items(): - print_status(f"Analysing {name} during {bench} ...") - os.environ["LD_PRELOAD"] = alloc["LD_PRELOAD"] - analyze_bench(bench) - - # save the resulting trace - for perm in bench.iterate_args(): - if bench.servers == []: - if perm: - perm_fmt = ("{}-" * (len(perm) - 1) + "{}").format(*perm) - else: - perm_fmt = "" - else: - perm_fmt = ANALYZSE_ALLOC_NAME - - old_trace = os.path.join(bench.result_dir, f"{perm_fmt}.trace") - new_trace = os.path.join(bench.result_dir, - f"{name}_{perm_fmt}.trace") - os.rename(old_trace, new_trace) diff --git a/src/artifact.py b/src/artifact.py deleted file mode 100644 index ecedbe9..0000000 --- a/src/artifact.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Artifact classes - -An Artifact is a external ressource downloaded from the internet. -There are two flavours of artifacts available: archives and git repositories. -Both flavours are version controlled archive with a checksum and git repositories -with a specific checkout. -""" - -import os -from subprocess import CalledProcessError - -import src.globalvars -from src.util import print_status, print_info, print_debug, print_error, run_cmd, sha1sum - -ARTIFACT_STORE_DIR = os.path.join(src.globalvars.allocbenchdir, "cache") - - -class Artifact: - """Base class for external ressources""" - store = {} - - def __init__(self, name): - if name in Artifact.store: - raise Exception(f'duplicate artifact "{name}"') - - Artifact.store[name] = self - self.name = name - self.basedir = os.path.join(ARTIFACT_STORE_DIR, name) - - def _retrieve(self, cmd): - """Run cmd to retrieve the artifact""" - os.makedirs(self.basedir, exist_ok=True) - - print_status(f'Retrieving artifact "{self.name}" ...') - print_debug(f"By running: {cmd} in {self.basedir}") - run_cmd(cmd, output_verbosity=1, cwd=self.basedir) - - -class GitArtifact(Artifact): - """External git repository""" - def __init__(self, name, url): - super().__init__(name) - self.url = url - self.repo = os.path.join(self.basedir, "repo") - - def retrieve(self): - """clone the git repo""" - super()._retrieve( - ["git", "clone", "--recursive", "--bare", self.url, "repo"]) - - def provide(self, checkout, location=None): - """checkout new worktree at location""" - if not location: - location = os.path.join(self.basedir, checkout) - - # check if we have already provided this checkout - if os.path.exists(location): - try: - run_cmd(["git", "fetch", "--force"], output_verbosity=1, cwd=location) - except CalledProcessError: - print_error(f"Failed to update {location}") - raise - try: - run_cmd(["git", "reset", "--hard", checkout], output_verbosity=1, cwd=location) - except CalledProcessError: - print_error(f"Failed to update {location}") - raise - return location - - # check if we have already retrieved the repo - if not os.path.exists(self.repo): - self.retrieve() - - # update repo - print_status(f'Updating git repository "{self.name}" ...') - try: - run_cmd(["git", "fetch", "--force"], output_verbosity=1, cwd=self.repo) - except CalledProcessError: - print_error(f"Failed to update {self.name}") - raise - - worktree_cmd = ["git", "worktree", "add", location, checkout] - print_debug("create new worktree. By running: ", worktree_cmd, - f"in {self.repo}") - try: - run_cmd(worktree_cmd, output_verbosity=1, cwd=self.repo) - except CalledProcessError: - print_error(f"Failed to provide {self.name}") - raise - - submodule_init_cmd = [ - "git", "submodule", "update", "--init", "--recursive" - ] - print_debug("update submodules in worktree. By running: ", - f"{submodule_init_cmd} in {self.repo}") - run_cmd(submodule_init_cmd, output_verbosity=1, cwd=location) - return location - - -class ArchiveArtifact(Artifact): - """External archive""" - supported_formats = ["tar"] - - def __init__(self, name, url, archive_format, checksum): - super().__init__(name) - self.url = url - if archive_format not in self.supported_formats: - raise Exception( - f'Archive format "{format}" not in supported list {self.supported_formats}' - ) - self.archive_format = archive_format - self.archive = os.path.join(self.basedir, f"{self.name}.{self.archive_format}") - self.checksum = checksum - - def retrieve(self): - """download the archive""" - super()._retrieve(["wget", "-O", self.archive, self.url]) - - def provide(self, location=None): - """extract the archive""" - - # Download archive - if not os.path.exists(self.archive): - self.retrieve() - - # compare checksums - print_info("Verify checksum ...") - if sha1sum(self.archive) != self.checksum: - raise Exception( - f"Archive {self.archive} does not match provided checksum") - - if not location: - location = os.path.join(self.basedir, "content") - - # Check if we already provided the archive at location - if os.path.exists(location): - return location - - os.makedirs(location, exist_ok=True) - - # Extract archive - if self.archive_format == "tar": - cmd = ["tar", "Cxf", location, self.archive] - - print_debug(f"extract archive by running: {cmd} in {self.basedir}") - run_cmd(cmd, output_verbosity=1, cwd=self.basedir) - return location diff --git a/src/benchmark.py b/src/benchmark.py deleted file mode 100644 index 2fb2606..0000000 --- a/src/benchmark.py +++ /dev/null @@ -1,632 +0,0 @@ -# Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Benchmark class providing general purpose implementation of required methods""" - -import atexit -from collections import namedtuple -import errno -import copy -import csv -import itertools -import multiprocessing -import os -import subprocess -from time import sleep -import traceback - -import numpy as np - -import src.globalvars -import src.util -from src.util import print_status, print_error, print_warn -from src.util import print_info0, print_info, print_debug - - -class Benchmark: - """Default implementation of most methods allocbench expects from a benchmark""" - - # class member to remember if we are allowed to use perf - perf_allowed = None - - cmd = "false" - args = {} - measure_cmd_csv = False - measure_cmd = "perf stat -x, -d" - servers = [] - allocators = copy.deepcopy(src.globalvars.allocators) - - @staticmethod - def terminate_subprocess(proc, timeout=5): - """Terminate or kill a Popen object""" - - # Skip already terminated subprocess - if proc.poll() is not None: - return proc.communicate() - - print_info("Terminating subprocess", proc.args) - proc.terminate() - try: - outs, errs = proc.communicate(timeout=timeout) - print_info("Subprocess exited with ", proc.returncode) - except subprocess.TimeoutExpired: - print_error("Killing subprocess ", proc.args) - proc.kill() - outs, errs = proc.communicate() - - print_debug("Server Out:", outs) - print_debug("Server Err:", errs) - return outs, errs - - @staticmethod - def scale_threads_for_cpus(factor=1, min_threads=1, steps=10): - """Helper to scale thread count to execution units - - Return a list of numbers between start and multiprocessing.cpu_count() * factor - with len <= steps.""" - max_threads = int(multiprocessing.cpu_count() * factor) - - if steps > max_threads - min_threads + 1: - return list(range(min_threads, int(max_threads) + 1)) - - nthreads = [] - divider = 2 - while True: - factor = max_threads // divider - entries = max_threads // factor - if entries > steps - 1: - return sorted(list(set([min_threads] + nthreads + [max_threads]))) - - nthreads = [int((i + 1) * factor) for i in range(int(entries))] - divider *= 2 - - @staticmethod - def is_perf_allowed(): - """raise an exception if perf is not allowed on this system""" - if Benchmark.perf_allowed is None: - print_info("Check if you are allowed to use perf ...") - res = subprocess.run(["perf", "stat", "ls"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - - if res.returncode != 0: - print_error(f"Test perf run failed with exit status: {res.returncode}") - print_debug(res.stderr) - Benchmark.perf_allowed = False - else: - Benchmark.perf_allowed = True - - if not Benchmark.perf_allowed: - raise Exception("You don't have the needed permissions to use perf") - - def __str__(self): - return self.name - - def __init__(self, name): - """Initialize a benchmark with default members if they aren't set already""" - self.name = name - - # Set result_dir - if not hasattr(self, "result_dir"): - self.result_dir = os.path.abspath(os.path.join(src.globalvars.resdir or "", - self.name)) - # Set build_dir - if not hasattr(self, "build_dir"): - self.build_dir = os.path.abspath(os.path.join(src.globalvars.builddir, - "benchmarks", self.name)) - - self.Perm = namedtuple("Perm", self.args.keys()) - - default_results = {"args": self.args, - "allocators": self.allocators, - "facts": {"libcs": {}, - "versions": {}}} - default_results.update({alloc: {} for alloc in self.allocators}) - - if not hasattr(self, "results"): - self.results = default_results - # Add default default entrys to self.results if their key is absent - else: - for key, default in default_results.items(): - if key not in self.results: - self.results[key] = default - - if self.servers: - self.results["servers"] = {} - - if not hasattr(self, "requirements"): - self.requirements = [] - - print_debug("Creating benchmark", self.name) - print_debug("Cmd:", self.cmd) - print_debug("Args:", self.args) - print_debug("Servers:", self.servers) - print_debug("Requirements:", self.requirements) - print_debug("Results dictionary:", self.results) - print_debug("Results directory:", self.result_dir) - - def save(self, path=None): - """Save benchmark results to a json file""" - import json - if not path: - path = self.name + ".json" - elif os.path.isdir(path): - path = os.path.join(path, self.name + ".json") - - print_info(f"Saving results to: {path}") - # JSON can't handle namedtuples so convert the dicts of namedtuples - # into lists of dicts. - save_data = {} - save_data.update(self.results) - save_data["stats"] = {} - for allocator in self.results["allocators"]: - # Skip allocators without measurements - if self.results[allocator] == {}: - continue - - measures = [] - stats = [] - for ntuple in self.iterate_args(args=self.results["args"]): - measures.append((ntuple._asdict(), - self.results[allocator][ntuple])) - - if "stats" in self.results: - stats.append((ntuple._asdict(), - self.results["stats"][allocator][ntuple])) - - save_data[allocator] = measures - if "stats" in self.results: - save_data["stats"][allocator] = stats - - with open(path, "w") as f: - json.dump(save_data, f) - - def load(self, path=None): - """Load benchmark results from file""" - if not path: - filename = self.name - else: - if os.path.isdir(path): - filename = os.path.join(path, self.name) - else: - filename = os.path.splitext(path) - - if os.path.exists(filename + ".json"): - import json - filename += ".json" - with open(filename, "r") as f: - self.results = json.load(f) - elif os.path.exists(filename + ".save"): - import pickle - filename += ".save" - with open(filename, "rb") as f: - self.results = pickle.load(f) - else: - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), filename) - - print_info(f"Loading results from: {filename}") - - # Build new named tuples - for allocator in self.results["allocators"]: - d = {} - for perm, measures in self.results[allocator]: - d[self.Perm(**perm)] = measures - self.results[allocator] = d - - d = {} - if "stats" in self.results: - for perm, value in self.results["stats"][allocator]: - d[self.Perm(**perm)] = value - self.results["stats"][allocator] = d - - # add eventual missing statistics - if "stats" not in self.results: - self.calc_desc_statistics() - - def prepare(self): - """default prepare implementation raising an error if a requirement is not found""" - os.environ["PATH"] += f"{os.pathsep}{src.globalvars.builddir}/benchmarks/{self.name}" - - for r in self.requirements: - exe = src.util.find_cmd(r) - if exe is not None: - self.results["facts"]["libcs"][r] = src.facter.libc_ver(executable=exe) - else: - raise Exception("Requirement: {} not found".format(r)) - - def iterate_args(self, args=None, fixed=None): - """Iterator over each possible combination of args - - Parameters - ---------- - args : dict, optional, default=None - Dictionary of arguments and iterables with their possible values. - If not provided defaults to :rc:`self.args` - - fixed : dict, optional, default=None - Mapping of arguments to one of their values. The yielded result - contains this value. If not provided defaults to :rc:`{}`. - - Returns - ------- - perm : :rc:`self.Perm` - A namedtuple containing one permutation of the benchmark's arguments. - - Examples - -------- - args = {"a1": [1,2], "a2": ["foo", "bar"]} - - self.iterate_args(args=args) yields [(1, "foo"), (2, "foo"), (1, "bar"), (2,"bar")] - self.iterate_args(args, {"a2":"bar"}) yields [(1, "bar"), (2, "bar")] - self.iterate_args(args, {"a1":2, "a2":"foo"}) yields [(2, "foo")]""" - if not args: - args = self.args - if not fixed: - fixed = {} - - for perm in itertools.product(*[args[k] for k in args]): - perm = self.Perm(*perm) - p_dict = perm._asdict() - is_fixed = True - for arg in fixed: - if p_dict[arg] != fixed[arg]: - is_fixed = False - break - - if is_fixed: - yield perm - - def prepare_argv(self, cmd, env={}, alloc={}, substitutions={}, prepend=True): - """Prepare an complete argv list for benchmarking""" - argv = [] - if prepend: - if "cmd_prefix" in alloc: - prefix_argv = alloc["cmd_prefix"].format(**substitutions).split() - argv.extend(prefix_argv) - # add exec wrapper so that a possible prefixed loader can execute shell scripts - argv.append(f"{src.globalvars.builddir}/exec") - - if self.measure_cmd != "": - measure_argv = self.measure_cmd.format(**substitutions) - measure_argv = src.util.prefix_cmd_with_abspath(measure_argv).split() - argv.extend(measure_argv) - - argv.append(f"{src.globalvars.builddir}/exec") - - ld_preload = f"{src.globalvars.builddir}/print_status_on_exit.so" - ld_preload += f" {src.globalvars.builddir}/sig_handlers.so" - - if "LD_PRELOAD" in env or alloc.get("LD_PRELOAD", ""): - ld_preload += f" {alloc.get('LD_PRELOAD', '')}" - ld_preload += " " + env.get('LD_PRELOAD', '') - - argv.extend(["-p", ld_preload]) - - if "LD_LIBRARY_PATH" in env or alloc.get("LD_LIBRARY_PATH", ""): - argv.extend(["-l", f"{alloc.get('LD_LIBRARY_PATH', '')} {env.get('LD_LIBRARY_PATH', '')}"]) - - cmd_argv = cmd.format(**substitutions) - cmd_argv = src.util.prefix_cmd_with_abspath(cmd_argv).split() - - argv.extend(cmd_argv) - - return argv - - def start_servers(self, env={}, alloc_name="None", alloc={"cmd_prefix": ""}): - """Start Servers - - Servers are not allowed to deamonize because then they can't - be terminated using their Popen object.""" - - substitutions = {"alloc": alloc_name, - "perm": alloc_name, - "builddir": src.globalvars.builddir} - - substitutions.update(self.__dict__) - substitutions.update(alloc) - - for server in self.servers: - server_name = server.get("name", "Server") - print_info(f"Starting {server_name} for {alloc_name}") - - argv = self.prepare_argv(server["cmd"], env, alloc, substitutions) - print_debug(argv) - - proc = subprocess.Popen(argv, env=env, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - - # TODO: check if server is up - sleep(5) - - ret = proc.poll() - if ret is not None: - print_debug("Stdout:", proc.stdout.read()) - print_debug("Stderr:", proc.stderr.read()) - raise Exception(f"Starting {server_name} failed with exit code: {ret}") - server["popen"] = proc - # Register termination of the server - atexit.register(Benchmark.shutdown_server, self=self, server=server) - - self.results["servers"].setdefault(alloc_name, {s["name"]: {"stdout": [], "stderr": [], "returncode": []} for s in self.servers}) - - if not "prepare_cmds" in server: - continue - - print_info(f"Preparing {server_name}") - for prep_cmd in server["prepare_cmds"]: - prep_cmd = prep_cmd.format(**substitutions) - print_debug(prep_cmd) - - proc = subprocess.run(prep_cmd.split(), universal_newlines=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - print_debug("Stdout:", proc.stdout) - print_debug("Stderr:", proc.stderr) - - - def shutdown_server(self, server): - """Terminate a started server running its shutdown_cmds in advance""" - if server["popen"].poll() == None: - server_name = server.get("name", "Server") - print_info(f"Shutting down {server_name}") - - substitutions = {} - substitutions.update(self.__dict__) - substitutions.update(server) - - if "shutdown_cmds" in server: - for shutdown_cmd in server["shutdown_cmds"]: - shutdown_cmd = shutdown_cmd.format(**substitutions) - print_debug(shutdown_cmd) - - proc = subprocess.run(shutdown_cmd.split(), universal_newlines=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - print_debug("Stdout:", proc.stdout) - print_debug("Stderr:", proc.stderr) - - # wait for server termination - sleep(5) - - outs, errs = Benchmark.terminate_subprocess(server["popen"]) - else: - outs = server["popen"].stdout.read() - errs = server["popen"].stderr.read() - - server["stdout"] = outs - server["stderr"] = errs - - def shutdown_servers(self): - """Terminate all started servers""" - print_info("Shutting down servers") - for server in self.servers: - self.shutdown_server(server) - - def run(self, runs=3): - """generic run implementation""" - - # check if we are allowed to use perf - if self.measure_cmd.startswith("perf"): - Benchmark.is_perf_allowed() - - # add benchmark dir to PATH - os.environ["PATH"] += f"{os.pathsep}{src.globalvars.builddir}/benchmarks/{self.name}" - - # save one valid result to expand invalid results - valid_result = {} - - self.results["facts"]["runs"] = runs - - n = len(list(self.iterate_args())) * len(self.allocators) - for run in range(1, runs + 1): - print_status(run, ". run", sep='') - - i = 0 - for alloc_name, alloc in self.allocators.items(): - if alloc_name not in self.results: - self.results[alloc_name] = {} - - skip = False - try: - self.start_servers(alloc_name=alloc_name, alloc=alloc, env=os.environ) - except Exception as e: - print_debug(traceback.format_exc()) - print_error(e) - print_error("Skipping", alloc_name) - skip = True - - # Preallocator hook - if hasattr(self, "preallocator_hook"): - self.preallocator_hook((alloc_name, alloc), run, os.environ) - - # Run benchmark for alloc - for perm in self.iterate_args(): - i += 1 - - # create new result entry - if perm not in self.results[alloc_name]: - self.results[alloc_name][perm] = [] - - # starting the server failed -> add empty result and continue - if skip: - self.results[alloc_name][perm].append({}) - continue - - print_info0(i, "of", n, "\r", end='') - - # Available substitutions in cmd - substitutions = {"run": run, "alloc": alloc_name} - substitutions.update(self.__dict__) - substitutions.update(alloc) - if perm: - substitutions.update(perm._asdict()) - substitutions["perm"] = "-".join([str(v) for v in perm]) - else: - substitutions["perm"] = "" - - # we measure the cmd -> prepare it accordingly - if not self.servers: - argv = self.prepare_argv(self.cmd, os.environ, alloc, substitutions) - # we measure the server -> run cmd as it is - else: - argv = self.prepare_argv(self.cmd, substitutions=substitutions, prepend=False) - - cwd = os.getcwd() - if hasattr(self, "run_dir"): - run_dir = self.run_dir.format(**substitutions) - os.chdir(run_dir) - print_debug("\nChange cwd to:", run_dir) - - print_debug("\nCmd:", argv) - res = subprocess.run(argv, stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - universal_newlines=True) - - result = {} - - if res.returncode != 0 or "ERROR: ld.so" in res.stderr or "Segmentation fault" in res.stderr or "Aborted" in res.stderr: - print() - print_debug("Stdout:\n" + res.stdout) - print_debug("Stderr:\n" + res.stderr) - if res.returncode != 0: - print_error(f"{argv} failed with exit code {res.returncode} for {alloc_name}") - elif "ERROR: ld.so" in res.stderr: - print_error(f"Preloading of {alloc['LD_PRELOAD']} failed for {alloc_name}") - else: - print_error(f"{argv} terminated abnormally") - - # parse and store results - else: - if not self.servers: - if os.path.isfile("status"): - # Read VmHWM from status file. If our benchmark - # didn't fork the first occurance of VmHWM is from - # our benchmark - with open("status", "r") as f: - for l in f.readlines(): - if l.startswith("VmHWM:"): - result["VmHWM"] = l.split()[1] - break - - os.remove("status") - - # parse perf output if available - if self.measure_cmd == Benchmark.measure_cmd or self.measure_cmd_csv: - csvreader = csv.reader(res.stderr.splitlines(), - delimiter=',') - for row in csvreader: - # Split of the user/kernel space info to be better portable - try: - result[row[2].split(":")[0]] = row[0] - except Exception as e: - print_warn("Exception", e, "occured on", row, "for", - alloc_name, "and", perm) - else: - result["server_status"] = [] - for server in self.servers: - with open(f"/proc/{server['popen'].pid}/status", "r") as f: - server_status = f.read() - result["server_status"].append(server_status) - - for l in server_status.splitlines(): - if l.startswith("VmHWM:"): - result[f"{server.get('name', 'Server')}_vmhwm"] = l.split()[1] - break - - - if hasattr(self, "process_output"): - self.process_output(result, res.stdout, res.stderr, - alloc_name, perm) - - - # save a valid result so we can expand invalid ones - if valid_result is None: - valid_result = result - - self.results[alloc_name][perm].append(result) - - if os.getcwd() != cwd: - os.chdir(cwd) - - if self.servers != [] and not skip: - self.shutdown_servers() - - for server in self.servers: - server_result = self.results["servers"][alloc_name][server['name']] - server_result["stdout"].append(server["stdout"]) - server_result["stderr"].append(server["stderr"]) - server_result["returncode"].append(server["popen"].returncode) - - if hasattr(self, "postallocator_hook"): - self.postallocator_hook((alloc_name, alloc), run) - - print() - - # reset PATH - os.environ["PATH"] = os.environ["PATH"].replace(f"{os.pathsep}{src.globalvars.builddir}/benchmarks/{self.name}", "") - - # expand invalid results - if valid_result != {}: - for allocator in self.allocators: - for perm in self.iterate_args(): - for i, m in enumerate(self.results[allocator][perm]): - if m == {}: - self.results[allocator][perm][i] = {k: np.NaN for k in valid_result} - - self.calc_desc_statistics() - - def calc_desc_statistics(self): - """Calculate descriptive statistics for each datapoint""" - allocs = self.results["allocators"] - self.results["stats"] = {} - for alloc in allocs: - # Skip allocators without measurements - if self.results[alloc] == {}: - continue - - self.results["stats"][alloc] = {} - - for perm in self.iterate_args(args=self.results["args"]): - stats = {s: {} for s in ["min", "max", "mean", "median", "std", - "std_perc", - "lower_quartile", "upper_quartile", - "lower_whisker", "upper_whisker", - "outliers"]} - for dp in self.results[alloc][perm][0]: - try: - data = [float(m[dp]) for m in self.results[alloc][perm]] - except (TypeError, ValueError) as e: - continue - stats["min"][dp] = np.min(data) - stats["max"][dp] = np.max(data) - stats["mean"][dp] = np.mean(data) - stats["median"][dp] = np.median(data) - stats["std"][dp] = np.std(data, ddof=1) - stats["std_perc"][dp] = stats["std"][dp] / stats["mean"][dp] - stats["lower_quartile"][dp], stats["upper_quartile"][dp] = np.percentile(data, [25, 75]) - trimmed_range = stats["upper_quartile"][dp] - stats["lower_quartile"][dp] - stats["lower_whisker"][dp] = stats["lower_quartile"][dp] - trimmed_range - stats["upper_whisker"][dp] = stats["upper_quartile"][dp] + trimmed_range - outliers = [] - for d in data: - if d > stats["upper_whisker"][dp] or d < stats["lower_whisker"][dp]: - outliers.append(d) - stats["outliers"][dp] = outliers - - self.results["stats"][alloc][perm] = stats diff --git a/src/benchmarks/__init__.py b/src/benchmarks/__init__.py deleted file mode 100644 index 68b5e56..0000000 --- a/src/benchmarks/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""allocbench benchmark definitions""" diff --git a/src/benchmarks/blowup.py b/src/benchmarks/blowup.py deleted file mode 100644 index a4e65ea..0000000 --- a/src/benchmarks/blowup.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the blowup micro benchmark""" - -from src.benchmark import Benchmark -import src.plots as plt - - -class BenchmarkBlowup(Benchmark): - """Blowup micro benchmark - - Check if allocators reuse memory. - Thread behaviour: - 1. Do many allocations and frees (100MiB is the maximum of live allocations at all times) - 2. Start new thread - 3. Join new thread - A perfect reusing allocator would need 100MiB RSS and a non reusing allocator - would need 1GiB. - """ - def __init__(self): - name = "blowup" - - self.cmd = "blowup" - - self.requirements = ["blowup"] - super().__init__(name) - - def summary(self): - # hack ideal rss in data set - allocators = self.results["allocators"] - allocators["Ideal-RSS"] = {"color": "xkcd:gold"} - self.results["stats"]["Ideal-RSS"] = {} - for perm in self.iterate_args(args=self.results["args"]): - self.results["stats"]["Ideal-RSS"][perm] = { - "mean": { - "VmHWM": 1024 * 100 - }, - "std": { - "VmHWM": 0 - } - } - - plt.plot(self, - "{VmHWM}/1000", - plot_type='bar', - fig_options={ - 'ylabel': "VmHWM in MB", - 'title': "blowup test" - }, - file_postfix="vmhwm") - - plt.pgfplot(self, - self.iterate_args(self.results["args"]), - "'blowup'", - "{VmHWM}/1000", - xlabel="", - ylabel="VmHWM in MB", - title="blowup test", - postfix="vmhwm", - bar=True) - - del allocators["Ideal-RSS"] - del self.results["stats"]["Ideal-RSS"] - - # plt.export_stats_to_dataref(self, "VmHWM") - - -blowup = BenchmarkBlowup() diff --git a/src/benchmarks/blowup/Makefile b/src/benchmarks/blowup/Makefile deleted file mode 100644 index afb5f2a..0000000 --- a/src/benchmarks/blowup/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -OPTFLAGS ?= -O3 -DNDEBUG - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -.PHONY = all clean - -all: $(OBJDIR)/blowup - -$(OBJDIR)/blowup: blowup.c | $(OBJDIR) - @echo compiling $@... - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/blowup/blowup.c b/src/benchmarks/blowup/blowup.c deleted file mode 100644 index 37ba6d6..0000000 --- a/src/benchmarks/blowup/blowup.c +++ /dev/null @@ -1,115 +0,0 @@ -#include <malloc.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define NUM_THREADS 10 -#define LIFE_DATA (1024l * 1024 * 100) // 100 MiB -#define ALLOCATIONS 100000l // 100000 -#define MAX_SIZE (1024l * 16) // 16KiB - -typedef struct chunk { - struct chunk* next; - char data[]; -} chunk_t; - -static inline size_t rand_size() -{ - return (rand() % MAX_SIZE) + sizeof(chunk_t); -} - -static void do_work() -{ - chunk_t* head = NULL; - chunk_t* tail = NULL; - size_t to_allocate = LIFE_DATA; - - // allocate life data - while(to_allocate > 0) { - size_t size = rand_size(); - if (size > to_allocate) - size = to_allocate; - - to_allocate -= size; - chunk_t* cur = (chunk_t*) malloc(size); - // touch memory - memset(&cur->data, 0, size - sizeof(struct chunk*)); - - if(!head) { - head = tail = cur; - } - else { - tail->next = cur; - tail = cur; - } - } - - // Do some random allocations to change the allocators state - for(int i = 0; i < ALLOCATIONS; i++) - { - free(malloc(rand_size())); - } - - // free life data - do { - chunk_t* next = head->next; - free(head); - head = next; - } while(head != tail); - - // Do some random allocations to change the allocators state - for(int i = 0; i < ALLOCATIONS; i++) - { - free(malloc(rand_size())); - } - - return; -} - -static void* thread_func(void* arg) -{ - unsigned int* thread_id = (unsigned int*)arg; - pthread_t next_thread; - - printf("thread %d doing work\n", *thread_id); - do_work(); - - if (*thread_id == NUM_THREADS) - return NULL; - - printf("thread %d spawning new thread work\n", *thread_id); - *thread_id = (*thread_id) + 1; - if (0 != pthread_create(&next_thread, NULL, thread_func, arg)) { - perror("pthread_create"); - return NULL; - } - - printf("thread %d joining thread %d work\n", *thread_id-1, *thread_id); - if (0 != pthread_join(next_thread, NULL)) { - perror("pthread_join"); - return NULL; - } - - return NULL; -} - -int main() -{ - unsigned int thread_count = 0; - pthread_t first; - - do_work(); - - if (0 != pthread_create(&first, NULL, thread_func, &thread_count)) { - perror("pthread_create"); - return 1; - } - - if (0 != pthread_join(first, NULL)) { - perror("pthread_join"); - return 1; - } - - return 0; -} diff --git a/src/benchmarks/cfrac.py b/src/benchmarks/cfrac.py deleted file mode 100644 index 1f495e6..0000000 --- a/src/benchmarks/cfrac.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""cfrac is a single threaded implementation of the continued fraction factorization algorithm, -described by Zorn and Grunwald in their paper "Empirical Measurements of Six Allocation-intensive C Programs" in 1992. - -It is mentioned in: -* Dirk Grunwald et al. - 1992 - CustoMalloc: Efficient Synthesized Memory Allocators -* Emery Berger et al. - 2001 - Composing High-Performance Memory Allocators -* Emery Berger et al. - 2002 - Reconsidering Custom Memory Allocation -* Jason Evans - 2006 - A Scalable Concurrent malloc(3) Implementation for FreeBSD -* Daan Leijen et al. - 2019 - Mimalloc: Free List Sharding in Action - -It uses many small short-lived allocations. -Factorizing 175451865205073170563711388363274837927895 results in -43044885 allocator calls (malloc: 21522444, free: 21522441). - -Allocator portion of total cycles measured using perf record/report: -malloc 4.33% -free 7.74% - -Top 10 allocation sizes 99.95% of all allocations -1. 18 B occurred 8172763 times -2. 28 B occurred 3781894 times -3. 10 B occurred 2989673 times -4. 26 B occurred 2566937 times -5. 20 B occurred 2420915 times -6. 16 B occurred 1168569 times -7. 12 B occurred 203177 times -8. 14 B occurred 170914 times -9. 30 B occurred 21149 times -10. 44 B occurred 15922 times - -allocations <= 64 21522432 100.00% -allocations <= 1024 21522436 100.00% -allocations <= 4096 21522443 100.00% - -Histogram of sizes: -0 - 15 3363764 15.63% ******* -16 - 31 18132778 84.25% ****************************************** -32 - 47 25888 0.12% -... - -The relevant non functional allocator properties are the raw speed of the -API function as well as memory placement strategies with good data locality. -""" - -from src.benchmark import Benchmark -import src.plots as plt - - -class BenchmarkCfrac(Benchmark): - """Definition of the cfrac benchmark""" - def __init__(self): - name = "cfrac" - - self.cmd = "cfrac{binary_suffix} {num}" - - self.args = {"num": [175451865205073170563711388363274837927895]} - - self.requirements = ["cfrac"] - super().__init__(name) - - def summary(self): - # Speed - plt.plot(self, - "{task-clock}/1000", - plot_type='bar', - fig_options={ - 'ylabel': 'cpu-second', - 'title': 'Cfrac: runtime', - }, - file_postfix="time") - - # L1 cache misses - plt.plot( - self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - plot_type='bar', - fig_options={ - 'ylabel': "L1 misses in %", - 'title': "Cfrac l1 cache misses", - 'yerr': False - }, - file_postfix="l1misses") - - # Memusage - plt.plot(self, - "{VmHWM}", - plot_type='bar', - fig_options={ - 'ylabel': "VmHWM in KB", - 'title': "Cfrac VmHWM", - }, - file_postfix="vmhwm") - - plt.write_tex_table(self, [{ - "label": "Runtime [ms]", - "expression": "{task-clock}", - "sort": "<" - }, { - "label": "Memusage [KB]", - "expression": "{VmHWM}", - "sort": "<" - }], - file_postfix="table") - - plt.export_stats_to_dataref(self, "task-clock") - - plt.export_stats_to_dataref(self, "VmHWM") - - -cfrac = BenchmarkCfrac() diff --git a/src/benchmarks/cfrac/CMakeLists.txt b/src/benchmarks/cfrac/CMakeLists.txt deleted file mode 100644 index b84d68c..0000000 --- a/src/benchmarks/cfrac/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(cfrac C) - -set(CMAKE_BUILD_TYPE "Release") - -set(cfrac_sources - cfrac.c - pops.c pconst.c pio.c - pabs.c pneg.c pcmp.c podd.c phalf.c - padd.c psub.c pmul.c pdivmod.c psqrt.c ppowmod.c - atop.c ptoa.c itop.c utop.c ptou.c errorp.c - pfloat.c pidiv.c pimod.c picmp.c - primes.c pcfrac.c pgcd.c) - -add_executable(cfrac ${cfrac_sources}) -target_compile_options(cfrac PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>) -target_compile_definitions(cfrac PRIVATE NOMEMOPT=1) -target_link_libraries(cfrac m) diff --git a/src/benchmarks/cfrac/README.md b/src/benchmarks/cfrac/README.md deleted file mode 100644 index 529480a..0000000 --- a/src/benchmarks/cfrac/README.md +++ /dev/null @@ -1,5 +0,0 @@ -pcfrac: Implementation of the continued fraction factoring algoritm - -Every two digits additional appears to double the factoring time - -Written by Dave Barrett (barrett%asgard@boulder.Colorado.EDU) diff --git a/src/benchmarks/cfrac/asm16bit.h b/src/benchmarks/cfrac/asm16bit.h deleted file mode 100644 index 2fb6e48..0000000 --- a/src/benchmarks/cfrac/asm16bit.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * HP-UX C compiler conventions - * - * Args pushed right-to-left; caller pops args on return - * Function result returned in d0 or d0(msb) d1(lsb) pair - * Called function must preserve all registers except d0,d1,a0,a1 - * C Registers are allocated from top-to-bottem in text from d7-d2, a5-a2 - */ -#ifdef __STDC__ -extern digit memaddw(digitPtr, digitPtr, digitPtr, posit); -extern digit memsubw(digitPtr, digitPtr, digitPtr, posit); - -extern digit memincw(digitPtr, accumulator); -extern digit memdecw(digitPtr, accumulator); - -extern digit memmulw(digitPtr, digitPtr, posit, digitPtr, posit); - -extern digit memdivw(digitPtr, digitPtr, posit, digitPtr); -extern digit memdivw1(digitPtr, digitPtr, posit, digit); -extern digit memmulw1(digitPtr, digitPtr, posit, digit); -extern digit memmodw1(digitPtr, posit, digit); - -extern void memlsrw(digitPtr, posit); -#else -extern digit memaddw(); -extern digit memsubw(); - -extern digit memincw(); -extern digit memdecw(); - -extern digit memmulw(); - -extern digit memdivw(); -extern digit memdivw1(); -extern digit memmulw1(); -extern digit memmodw1(); - -extern void memlsrw(); -#endif diff --git a/src/benchmarks/cfrac/atop.c b/src/benchmarks/cfrac/atop.c deleted file mode 100644 index 98f132a..0000000 --- a/src/benchmarks/cfrac/atop.c +++ /dev/null @@ -1,61 +0,0 @@ -#include <ctype.h> -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * ascii to precision (modeled after atoi) - * leading whitespace skipped - * an optional leading '-' or '+' followed by digits '0'..'9' - * leading 0's Ok - * stops at first unrecognized character - * - * Returns: pUndef if an invalid argument (pUndef or nondigit as 1st digit) - */ -precision atop(chp) - register char *chp; -{ - precision res = pUndef; - precision clump = pUndef; - int sign = 0; - register int ch; - register accumulator temp; - accumulator x; - register int i; - - if (chp != (char *) 0) { - while (isspace(*chp)) chp++; /* skip whitespace */ - if (*chp == '-') { - sign = 1; - ++chp; - } else if (*chp == '+') { - ++chp; - } - if (isdigit(ch = * (unsigned char *) chp)) { - pset(&res, pzero); - pset(&clump, utop(aDigit)); - do { - i = aDigitLog-1; - temp = ch - '0'; - do { - if (!isdigit(ch = * (unsigned char *) ++chp)) goto atoplast; - temp = temp * aBase + (ch - '0'); - } while (--i > 0); - pset(&res, padd(pmul(res, clump), utop(temp))); - } while (isdigit(ch = * (unsigned char *) ++chp)); - goto atopdone; -atoplast: - x = aBase; - while (i++ < aDigitLog-1) { - x *= aBase; - } - pset(&res, padd(pmul(res, utop(x)), utop(temp))); -atopdone: - if (sign) { - pset(&res, pneg(res)); - } - } - } - pdestroy(clump); - return presult(res); -} diff --git a/src/benchmarks/cfrac/cfrac.c b/src/benchmarks/cfrac/cfrac.c deleted file mode 100644 index 9185d18..0000000 --- a/src/benchmarks/cfrac/cfrac.c +++ /dev/null @@ -1,268 +0,0 @@ -#include <string.h> -#include <stdio.h> -#include <math.h> /* for findk */ - -#if defined(_WIN32) -#include <windows.h> -#endif - -#include "pdefs.h" - -#ifdef __STDC__ -#include <stdlib.h> -#endif -#include "precision.h" -#include "pfactor.h" - -#ifdef __STDC__ -extern unsigned *pfactorbase(precision n, unsigned k, - unsigned *m, unsigned aborts); -extern double pomeranceLpow(double n, double alpha); -#else -extern unsigned *pfactorbase(); -extern double pomeranceLpow(); -#endif - -int verbose = 0; -int debug = 0; - -extern unsigned cfracNabort; -extern unsigned cfracTsolns; -extern unsigned cfracPsolns; -extern unsigned cfracT2solns; -extern unsigned cfracFsolns; - - -extern unsigned short primes[]; -extern unsigned primesize; - -/* - * Return the value of "f(p,d)" from Knuth's exercise 28 - */ -float pfKnuthEx28(p, d) - unsigned p; - precision d; -{ - register float res; - precision k = pUndef; - - (void) pparm(d); - if (p == 2) { - if (peven(d)) { - pset(&k, phalf(d)); - if (peven(k)) { - res = 2.0/3.0 + pfKnuthEx28(2,k)/2.0; /* eliminate powers of 2 */ - } else { /* until only one 2 left in d. */ - res = 1.0/3.0; /* independent of (the now odd) k. Wow! */ - } - } else { /* d now odd */ - pset(&k, phalf(d)); - if (podd(k)) { - res = 1.0/3.0; /* f(2,4k+3): d%8 == 3 or 7 */ - } else { - if (podd(phalf(k))) { - res = 2.0/3.0; /* f(2,8k+5): d%8 == 5 */ - } else { - res = 4.0/3.0; /* f(2,8k+1): d%8 == 1 */ - } - } - } - } else { /* PART 3: p odd, d could still be even (OK) */ - pset(&k, utop(p)); - if peq(ppowmod(d, phalf(psub(k, pone)), k), pone) { - res = (float) (p+p) / (((float) p)*p-1.0); /* beware int overflow! */ - } else { - res = 0.0; - } - } - - pdestroy(k); - pdestroy(d); - if (debug > 1) { - fprintf(stdout, "f(%u,", p); - fprintf(stdout, "d) = %9.7f\n", res); - } - return res; -} - -float cfrac_logf(unsigned p, precision n, unsigned k) -{ - register float res; - - (void) pparm(n); - -#if 0 /* old code for non-float machines; not worth the cost */ - pset(&r, utop(k)); - log2sqrtk = plogb(pipow(r, q >> 1), ptwo); - fplog2p = (f(p,pmul(r,n),q) * plogb(pipow(utop(p),q),ptwo)+(q>>1))/q; -#endif - - res = pfKnuthEx28(p, pmul(itop(k),n)) * log((double) p); - /* res -= log((double) k) * 0.5; */ - - pdestroy(n); - return res; -} - -/* - * Find the best value of k for the given n and m. - * - * Input/Output: - * n - the number to factor - * m - pointer to size of factorbase (0 = select "best" size) - * aborts - the number of early aborts - */ -unsigned findk(n, m, aborts, maxk) - precision n; - register unsigned *m; - unsigned aborts, maxk; -{ - unsigned k, bestk = 0, count, bestcount = 0, maxpm; - float sum, max = -1.0E+15; /* should be small enough */ - unsigned *p; - register unsigned i; - register unsigned short *primePtr; - - (void) pparm(n); - - for (k = 1; k < maxk; k++) { /* maxk should best be m+m? */ - if (debug) { - fputs("kN = ", stdout); - fputp(stdout, pmul(utop(k), n)); putc('\n', stdout); - } - count = *m; - p = pfactorbase(n, k, &count, aborts); - if (p == (unsigned *) 0) { - fprintf(stderr, "couldn't compute factor base in findk\n"); - exit(1); - } - - maxpm = p[count-1]; - - sum = 0.0; - primePtr = primes; - while (*primePtr <= maxpm) { - sum += cfrac_logf((unsigned) *primePtr++, n, k); - } - sum -= log((double) k) * 0.5; - if (verbose > 2) fprintf(stdout, "%u: %5.2f", k, sum); - if (debug) fprintf(stdout, " log(k)/2=%5.2f", log((double) k) * 0.5); - if (verbose > 2) { - fputs("\n", stdout); - fflush(stdout); - } - if (sum > max) { - max = sum; - bestk = k; - bestcount = count; - } -#ifndef IGNOREFREE - free(p); -#endif - } - - *m = bestcount; - pdestroy(n); - return bestk; -} - -extern char *optarg; -extern int optind; - -char *progName; - -extern int getopt(); - -int main(argc, argv) - int argc; - char *argv[]; -{ - unsigned m = 0, k = 0; - unsigned maxCount = 1<<30, count, maxk = 0; - int ch; - precision n = pUndef, f = pUndef; - unsigned aborts = 3; - unsigned *p; - double d; - - progName = *argv; - - while ((ch = getopt(argc, argv, "a:k:i:dv")) != EOF) switch (ch) { - case 'a': - aborts = atoi(optarg); - break; - case 'k': - maxk = atoi(optarg); - break; - case 'i': - maxCount = atoi(optarg); - break; - case 'd': - debug++; - break; - case 'v': - verbose++; - break; - default: -usage: fprintf(stderr, - "usage: %s [-dv] [-a aborts ] [-k maxk ] [-i maxCount ] n [[ m ] k ]\n", - progName); - return 1; - } - argc -= optind; - argv += optind; - - if (argc == 0) { - argc = 1; - static char* argvx[2] = { "17545186520507317056371138836327483792736", NULL }; - argv = argvx; - } - - if (argc < 1 || argc > 3) goto usage; - - pset(&n, atop(*argv++)); --argc; - if (argc) { m = atoi(*argv++); --argc; } - if (argc) { k = atoi(*argv++); --argc; } - - if (k == 0) { - if (maxk == 0) { - maxk = m / 2 + 5; - if (verbose) fprintf(stdout, "maxk = %u\n", maxk); - } - k = findk(n, &m, aborts, maxk); - if (verbose) { - fprintf(stdout, "k = %u\n", k); - } - } - - count = maxCount; - - pcfracInit(m, k, aborts); - - pset(&f, pcfrac(n, &count)); - count = maxCount - count; - if (verbose) { - putc('\n', stdout); - fprintf(stdout, "Iterations : %u\n", count); - fprintf(stdout, "Early Aborts : %u\n", cfracNabort); - fprintf(stdout, "Total Partials : %u\n", cfracTsolns); - fprintf(stdout, "Used Partials : %u\n", cfracT2solns); - fprintf(stdout, "Full Solutions : %u\n", cfracPsolns); - fprintf(stdout, "Factor Attempts: %u\n", cfracFsolns); - } - - if (f != pUndef) { - fputp(stdout, n); - fputs(" = ", stdout); - fputp(stdout, f); - fputs(" * ", stdout); - pdivmod(n, f, &n, pNull); - fputp(stdout, n); - putc('\n', stdout); - } - - pdestroy(f); - pdestroy(n); - - return 0; -} diff --git a/src/benchmarks/cfrac/errorp.c b/src/benchmarks/cfrac/errorp.c deleted file mode 100644 index 5868aa4..0000000 --- a/src/benchmarks/cfrac/errorp.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <stdio.h> -#include "precision.h" - -/* - * Fatal error (user substitutable) - * - * PNOMEM - out of memory (pcreate) - * PREFCOUNT - refcount negative (pdestroy) - * PUNDEFINED - undefined value referenced (all) - * PDOMAIN - domain error - * pdivmod: divide by zero - * psqrt: negative argument - * POVERFLOW - overflow - * itop: too big - */ -precision errorp(errnum, routine, message) - int errnum; - char *routine; - char *message; -{ - fputs(routine, stderr); - fputs(": ", stderr); - fputs(message, stderr); - fputs("\n", stderr); - abort(); /* remove this line if you want */ - return pUndef; -} diff --git a/src/benchmarks/cfrac/getopt.c b/src/benchmarks/cfrac/getopt.c deleted file mode 100644 index 788c2cb..0000000 --- a/src/benchmarks/cfrac/getopt.c +++ /dev/null @@ -1,757 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. - Ditto for AIX 3.2 and <stdlib.h>. */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - -#include <string.h> - -#ifdef HAVE_CONFIG_H -#if defined (emacs) || defined (CONFIG_BROKETS) -/* We use <config.h> instead of "config.h" so that a compilation - using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h - (which it would do because it found this file in $srcdir). */ -#include <config.h> -#else -#include "config.h" -#endif -#endif - -#ifndef __STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include <stdio.h> - -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -#include <stdlib.h> -#endif /* GNU C library. */ - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = NULL; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* XXX 1003.2 says this must be 1 before any call. */ -int optind = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return EOF with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -#include <string.h> -#define my_index strchr -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#ifndef __STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (optstring) - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns `EOF'. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0) - optstring = _getopt_initialize (optstring); - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0')) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return EOF; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) - { - if (ordering == REQUIRE_ORDER) - return EOF; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if (nameend - nextchar == (int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, "%s: option `%s' is ambiguous\n", - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[optind - 1][0], pfound->name); - } - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, "%s: option `%s' requires an argument\n", - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, "%s: unrecognized option `--%s'\n", - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, "%s: unrecognized option `%c%s'\n", - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); - else - fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); - } - optopt = c; - return '?'; - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: option requires an argument -- %c\n", - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* _LIBC or not __GNU_LIBRARY__. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == EOF) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/src/benchmarks/cfrac/getopt.h b/src/benchmarks/cfrac/getopt.h deleted file mode 100644 index 7fc2cca..0000000 --- a/src/benchmarks/cfrac/getopt.h +++ /dev/null @@ -1,125 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -#if __STDC__ - const char *name; -#else - char *name; -#endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -#if __STDC__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. We used to try to prototype - it if __GNU_LIBRARY__ but that wasn't problem free either (I'm not sure - exactly why), and there is no particular need to prototype it. - We really shouldn't be trampling on the system's namespace at all by - declaring getopt() but that is a bigger issue. */ -extern int getopt (); - -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); -#else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -#endif /* not __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/src/benchmarks/cfrac/itop.c b/src/benchmarks/cfrac/itop.c deleted file mode 100644 index 87d309a..0000000 --- a/src/benchmarks/cfrac/itop.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Integer to Precision - */ -precision itop(i) - register int i; -{ - register digitPtr uPtr; - register precision u = palloc(INTSIZE); - - if (u == pUndef) return u; - - if (u->sign = (i < 0)) i = -i; - uPtr = u->value; - do { - *uPtr++ = modBase(i); - i = divBase(i); - } while (i != 0); - - u->size = (uPtr - u->value); /* normalize */ - return presult(u); -} diff --git a/src/benchmarks/cfrac/ltop.c b/src/benchmarks/cfrac/ltop.c deleted file mode 100644 index 33eaea5..0000000 --- a/src/benchmarks/cfrac/ltop.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Long to Precision - */ -precision ltop(l) - register long l; -{ - register digitPtr uPtr; - register precision u = palloc(LONGSIZE); - - if (u == pUndef) return u; - - if (u->sign = (l < 0L)) l = -l; - uPtr = u->value; - do { - *uPtr++ = modBase(l); - l = divBase(l); - } while (l != 0); - - u->size = (uPtr - u->value); /* normalize */ - return presult(u); -} diff --git a/src/benchmarks/cfrac/pabs.c b/src/benchmarks/cfrac/pabs.c deleted file mode 100644 index 674cf1b..0000000 --- a/src/benchmarks/cfrac/pabs.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "pdefs.h" /* private include file */ -#include "precision.h" /* public include file for forward refs */ -#include <string.h> - -/* - * absolute value - */ -precision pabs(u) - register precision u; -{ - register precision w; - - (void) pparm(u); - w = palloc(u->size); - if (w == pUndef) return w; - - w->sign = false; - (void) memcpy(w->value, u->value, u->size * sizeof(digit)); - - pdestroy(u); - return presult(w); -} diff --git a/src/benchmarks/cfrac/padd.c b/src/benchmarks/cfrac/padd.c deleted file mode 100644 index 62b93d5..0000000 --- a/src/benchmarks/cfrac/padd.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "pdefs.h" -#include "precision.h" -#include <string.h> - -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Add - * - * This will work correctly if -0 is passed as input - */ -precision padd(u, v) - register precision v; -#ifndef ASM_16BIT - precision u; -{ - register digitPtr wPtr, uPtr, vPtr; -#else - register precision u; -{ - register digitPtr wPtr; - digitPtr uPtr; -#endif - precision w; /* function result */ - register accumulator temp; /* 0 <= temp < 2*base */ - register digit carry; /* 0 <= carry <= 1 */ -#ifdef ASM_16BIT - register int size; -#endif - - (void) pparm(u); - (void) pparm(v); - if (u->sign != v->sign) { /* Are we are actually subtracting? */ - w = pUndef; - if (v->sign) { - v->sign = !v->sign; /* can't generate -0 */ - pset(&w, psub(u, v)); - v->sign = !v->sign; - } else { - u->sign = !u->sign; /* can't generate -0 */ - pset(&w, psub(v, u)); - u->sign = !u->sign; - } - } else { - if (u->size < v->size) { /* u is always biggest number */ - w = u; u = v; v = w; - } - - w = palloc(u->size+1); /* there is at most one added digit */ - if (w == pUndef) return w; /* arguments not destroyed */ - - w->sign = u->sign; - - uPtr = u->value; - wPtr = w->value; -#ifndef ASM_16BIT - vPtr = v->value; - carry = 0; - do { /* Add digits in both args */ - temp = *uPtr++ + *vPtr++; /* 0 <= temp < 2*base-1 */ - temp += carry; /* 0 <= temp < 2*base */ - carry = divBase(temp); /* 0 <= carry <= 1 */ - *wPtr++ = modBase(temp); /* mod has positive args */ - } while (vPtr < v->value + v->size); - - while (uPtr < u->value + u->size) { /* propogate carry */ - temp = *uPtr++ + carry; - carry = divBase(temp); - *wPtr++ = modBase(temp); - } - *wPtr = carry; -#else - size = v->size; - temp = u->size - size; - carry = memaddw(wPtr, uPtr, v->value, size); - if (temp > 0) { - memcpy(wPtr + size, uPtr + size, temp * sizeof(digit)); - if (carry) { - carry = memincw(wPtr + size, temp); - } - } - wPtr[u->size] = carry; /* yes, I do mean u->size */ -#endif - if (carry == 0) { - --(w->size); - } - } - - pdestroy(u); - pdestroy(v); - return presult(w); -} diff --git a/src/benchmarks/cfrac/pcfrac.c b/src/benchmarks/cfrac/pcfrac.c deleted file mode 100644 index 2a0d032..0000000 --- a/src/benchmarks/cfrac/pcfrac.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * pcfrac: Implementation of the continued fraction factoring algoritm - * - * Every two digits additional appears to double the factoring time - * - * Written by Dave Barrett (barrett%asgard@boulder.Colorado.EDU) - */ -#include <string.h> -#include <stdio.h> -#include <math.h> - -#ifdef __STDC__ -#include <stdlib.h> -#endif -#include "precision.h" -#include "pfactor.h" - -extern int verbose; - -unsigned cfracNabort = 0; -unsigned cfracTsolns = 0; -unsigned cfracPsolns = 0; -unsigned cfracT2solns = 0; -unsigned cfracFsolns = 0; - -extern unsigned short primes[]; -extern unsigned primesize; - -typedef unsigned *uptr; -typedef uptr uvec; -typedef unsigned char *solnvec; -typedef unsigned char *BitVector; - -typedef struct SolnStruc { - struct SolnStruc *next; - precision x; /* lhs of solution */ - precision t; /* last large prime remaining after factoring */ - precision r; /* accumulated root of pm for powers >= 2 */ - BitVector e; /* bit vector of factorbase powers mod 2 */ -} Soln; - -typedef Soln *SolnPtr; - -#define BPI(x) ((sizeof x[0]) << 3) - -void setBit(bv, bno, value) - register BitVector bv; - register unsigned bno, value; -{ - bv += bno / BPI(bv); - bno %= BPI(bv); - *bv |= ((value != 0) << bno); -} - -unsigned getBit(bv, bno) - register BitVector bv; - register unsigned bno; -{ - register unsigned res; - - bv += bno / BPI(bv); - bno %= BPI(bv); - res = (*bv >> bno) & 1; - - return res; -} - -BitVector newBitVector(value, size) - register solnvec value; - unsigned size; -{ - register BitVector res; - register solnvec vp = value + size; - unsigned msize = ((size + BPI(res)-1) / BPI(res)) * sizeof res[0]; - -#ifdef BWGC - res = (BitVector) gc_malloc(msize); -#else - res = (BitVector) malloc(msize); -#endif - if (res == (BitVector) 0) return res; - - memset(res, '\0', msize); - do { - if (*--vp) { - setBit(res, vp - value, (unsigned) *vp); - } - } while (vp != value); - return res; -} - -void printSoln(stream, prefix, suffix, pm, m, p, t, e) - FILE *stream; - char *prefix, *suffix; - register unsigned *pm, m; - precision p, t; - register solnvec e; -{ - register unsigned i, j = 0; - - for (i = 1; i <= m; i++) j += (e[i] != 0); - - fputs(prefix, stream); - fputp(stream, pparm(p)); fputs(" = ", stream); - if (*e & 1) putc('-', stream); else putc('+', stream); - fputp(stream, pparm(t)); - - if (j >= 1) fputs(" *", stream); - do { - e++; - switch (*e) { - case 0: break; - case 1: fprintf(stream, " %u", *pm); break; - default: - fprintf(stream, " %u^%u", *pm, (unsigned) *e); - } - pm++; - } while (--m); - - fputs(suffix, stream); - fflush(stream); - pdestroy(p); pdestroy(t); -} - -/* - * Combine two solutions - */ -void combineSoln(x, t, e, pm, m, n, bp) - precision *x, *t, n; - uvec pm; - register solnvec e; - unsigned m; - SolnPtr bp; -{ - register unsigned j; - - (void) pparm(n); - if (bp != (SolnPtr) 0) { - pset(x, pmod(pmul(bp->x, *x), n)); - pset(t, pmod(pmul(bp->t, *t), n)); - pset(t, pmod(pmul(bp->r, *t), n)); - e[0] += getBit(bp->e, 0); - } - e[0] &= 1; - for (j = 1; j <= m; j++) { - if (bp != (SolnPtr) 0) e[j] += getBit(bp->e, j); - if (e[j] > 2) { - pset(t, pmod(pmul(*t, - ppowmod(utop(pm[j-1]), utop((unsigned) e[j]>>1), n)), n)); - e[j] &= 1; - } else if (e[j] == 2) { - pset(t, pmod(pmul(*t, utop(pm[j-1])), n)); - e[j] = 0; - } - } - pdestroy(n); -} - -/* - * Create a normalized solution structure from the given inputs - */ -SolnPtr newSoln(n, pm, m, next, x, t, e) - precision n; - unsigned m; - uvec pm; - SolnPtr next; - precision x, t; - solnvec e; -{ -#ifdef BWGC - SolnPtr bp = (SolnPtr) gc_malloc(sizeof (Soln)); -#else - SolnPtr bp = (SolnPtr) malloc(sizeof (Soln)); -#endif - - if (bp != (SolnPtr) 0) { - bp->next = next; - bp->x = pnew(x); - bp->t = pnew(t); - bp->r = pnew(pone); - /* - * normalize e, put the result in bp->r and e - */ - combineSoln(&bp->x, &bp->r, e, pm, m, pparm(n), (SolnPtr) 0); - bp->e = newBitVector(e, m+1); /* BitVector */ - } - - pdestroy(n); - return bp; -} - -void freeSoln(p) - register SolnPtr p; -{ - if (p != (SolnPtr) 0) { - pdestroy(p->x); - pdestroy(p->t); - pdestroy(p->r); -#ifndef IGNOREFREE - free(p->e); /* BitVector */ - free(p); -#endif - } -} - -void freeSolns(p) - register SolnPtr p; -{ - register SolnPtr l; - - while (p != (SolnPtr) 0) { - l = p; - p = p->next; - freeSoln(l); - } -} - -SolnPtr findSoln(sp, t) - register SolnPtr sp; - precision t; -{ - (void) pparm(t); - while (sp != (SolnPtr) 0) { - if peq(sp->t, t) break; - sp = sp->next; - } - pdestroy(t); - return sp; -} - -static unsigned pcfrac_k = 1; -static unsigned pcfrac_m = 0; -static unsigned pcfrac_aborts = 3; - -/* - * Structure for early-abort. Last entry must be <(unsigned *) 0, uUndef> - */ -typedef struct { - unsigned *pm; /* bound check occurs before using this pm entry */ - precision bound; /* max allowable residual to prevent abort */ -} EasEntry; - -typedef EasEntry *EasPtr; - -void freeEas(eas) - EasPtr eas; -{ - register EasPtr ep = eas; - - if (ep != (EasPtr) 0) { - while (ep->pm != 0) { - pdestroy(ep->bound); - ep++; - } -#ifndef IGNOREFREE - free(eas); -#endif - } -} - -/* - * Return Pomerance's L^alpha (L = exp(sqrt(log(n)*log(log(n))))) - */ -double pomeranceLpow(n, y) - double n; - double y; -{ - double lnN = log(n); - double res = exp(y * sqrt(lnN * log(lnN))); - return res; -} - -/* - * Pomerance's value 'a' from page 122 "of Computational methods in Number - * Theory", part 1, 1982. - */ -double cfracA(n, aborts) - double n; - unsigned aborts; -{ - return 1.0 / sqrt(6.0 + 2.0 / ((double) aborts + 1.0)); -} - -/* - * Returns 1 if a is a quadratic residue of odd prime p, - * p-1 if non-quadratic residue, 0 otherwise (gcd(a,p)<>1) - */ -#define plegendre(a,p) ppowmod(a, phalf(psub(p, pone)), p) - -/* - * Create a table of small primes of quadratic residues of n - * - * Input: - * n - the number to be factored - * k - the multiple of n to be factored - * *m - the number of primes to generate (0 to select best) - * aborts - the number of early aborts - * - * Assumes that plegendre # 0, for if it is, that pm is a factor of n. - * This algorithm already assumes you've used trial division to eliminate - * all of these! - * - * Returns: the list of primes actually generated (or (unsigned *) 0 if nomem) - * *m changed to reflect the number of elements in the list - */ -uvec pfactorbase(n, k, m, aborts) - precision n; - unsigned k; - unsigned *m, aborts; -{ - double dn, a; - register unsigned short *primePtr = primes; - register unsigned count = *m; - unsigned maxpm = primes[primesize-1]; - unsigned *res = (uvec) 0, *pm; - precision nk = pnew(pmul(pparm(n), utop(k))); - - if (*m == 0) { /* compute a suitable m */ - dn = ptod(nk); - a = cfracA(dn, aborts); - maxpm = (unsigned) (pomeranceLpow(dn, a) + 0.5); - do { - if ((unsigned) *primePtr++ >= maxpm) break; - } while ((unsigned) *primePtr != 1); - count = primePtr - primes; - primePtr = primes; - } - /* - * This m tends to be too small for small n, and becomes closer to - * optimal as n goes to infinity. For 30 digits, best m is ~1.5 this m. - * For 38 digits, best m appears to be ~1.15 this m. It's appears to be - * better to guess too big than too small. - */ -#ifdef BWGC - res = (uvec) gc_malloc(count * sizeof (unsigned)); -#else - res = (uvec) malloc(count * sizeof (unsigned)); -#endif - if (res == (uvec) 0) goto doneMk; - - pm = res; - *pm++ = (unsigned) *primePtr++; /* two is first element */ - count = 1; - if (count != *m) do { - if (picmp(plegendre(nk, utop((unsigned) *primePtr)), 1) <= 0) { /* 0,1 */ - *pm++ = *primePtr; - count++; - if (count == *m) break; - if ((unsigned) *primePtr >= maxpm) break; - } - ++primePtr; - } while (*primePtr != 1); - *m = count; - -doneMk: - pdestroy(nk); - pdestroy(n); - return res; -} - -/* - * Compute Pomerance's early-abort-stragegy - */ -EasPtr getEas(n, k, pm, m, aborts) - precision n; - unsigned k, *pm, m, aborts; -{ - double x = 1.0 / ((double) aborts + 1.0); - double a = 1.0 / sqrt(6.0 + 2.0 * x); - double ax = a * x, csum = 1.0, tia = 0.0; - double dn, dpval, dbound, ci; - unsigned i, j, pval; - - precision bound = pUndef; - EasPtr eas; - - if (aborts == 0) return (EasPtr) 0; - -#ifdef BWGC - eas = (EasPtr) gc_malloc((aborts+1) * sizeof (EasEntry)); -#else - eas = (EasPtr) malloc((aborts+1) * sizeof (EasEntry)); -#endif - if (eas == (EasPtr) 0) return eas; - - dn = ptod(pmul(utop(k), pparm(n))); /* should this be n ? */ - for (i = 1; i <= aborts; i++) { - eas[i-1].pm = (unsigned *) 0; - eas[i-1].bound = pUndef; - tia += ax; - ci = 4.0 * tia * tia / (double) i; - csum -= ci; - dpval = pomeranceLpow(dn, tia); - dbound = pow(dn, 0.5 * csum); - - pval = (unsigned) (dpval + 0.5); - pset(&bound, dtop(dbound)); - for (j = 0; j < m; j++) { - if (pm[j] >= pval) goto foundpm; - } - break; -foundpm: - if (verbose > 1) { - printf(" Abort %u on p = %u (>=%u) and q > ", i, pm[j], pval); - fputp(stdout, bound); putc('\n', stdout); - fflush(stdout); - } - eas[i-1].pm = &pm[j]; - pset(&eas[i-1].bound, bound); - } - eas[i-1].pm = (unsigned *) 0; - eas[i-1].bound = pUndef; - - pdestroy(bound); - pdestroy(n); - - return eas; -} - -/* - * Factor the argument Qn using the primes in pm. Result stored in exponent - * vector e, and residual factor, f. If non-null, eas points to a list of - * early-abort boundaries. - * - * e is set to the number of times each prime in pm divides v. - * - * Returns: - * -2 - if factoring aborted because of early abort - * -1 - factoring failed - * 0 - if result is a "partial" factoring - * 1 - normal return (a "full" factoring) - */ -int pfactorQ(f, t, pm, e, m, eas) - precision *f; - precision t; - register unsigned *pm; - register solnvec e; - register unsigned m; - EasEntry *eas; -{ - precision maxp = pUndef; - unsigned maxpm = pm[m-1], res = 0; - register unsigned *pp = (unsigned *) 0; - - (void) pparm(t); - - if (eas != (EasEntry *) 0) { - pp = eas->pm; - pset(&maxp, eas->bound); - } - - memset((char *) e, '\0', m * sizeof e[0]); /* looks slow here, but isn't */ - - while (peven(t)) { /* assume 2 1st in pm; save time */ - pset(&t, phalf(t)); - (*e)++; - } - --m; - - do { - e++; pm++; - if (pm == pp) { /* check for early abort */ - if (pgt(t, maxp)) { - res = -2; - goto gotSoln; - } - eas++; - pp = eas->pm; - pset(&maxp, eas->bound); - } - while (pimod(t, (int) *pm) == 0) { - pset(&t, pidiv(t, (int) *pm)); - (*e)++; - } - } while (--m != 0); - res = -1; - if (picmp(t, 1) == 0) { - res = 1; - } else if (picmp(pidiv(t, (int) *pm), maxpm) <= 0) { -#if 0 /* it'll never happen; Honest! If so, pm is incorrect. */ - if (picmp(t, maxpm) <= 0) { - fprintf(stderr, "BUG: partial with t < maxpm! t = "); - fputp(stderr, t); putc('\n', stderr); - } -#endif - res = 0; - } -gotSoln: - pset(f, t); - pdestroy(t); pdestroy(maxp); - return res; -} - -/* - * Attempt to factor n using continued fractions (n must NOT be prime) - * - * n - The number to attempt to factor - * maxCount - if non-null, points to the maximum number of iterations to try. - * - * This algorithm may fail if it get's into a cycle or maxCount expires - * If failed, n is returned. - * - * This algorithm will loop indefinitiely in n is prime. - * - * This an implementation of Morrison and Brillhart's algorithm, with - * Pomerance's early abort strategy, and Knuth's method to find best k. - */ -precision pcfrac(n, maxCount) - precision n; - unsigned *maxCount; -{ - unsigned k = pcfrac_k; - unsigned m = pcfrac_m; - unsigned aborts = pcfrac_aborts; - SolnPtr oddt = (SolnPtr) 0, sp, bp, *b; - EasPtr eas = (EasPtr) 0; - uvec pm = (uvec) 0; - solnvec e = (solnvec) 0; - unsigned bsize, s = 0, count = 0; - register unsigned h, j; - int i; - - precision t = pUndef, - r = pUndef, twog = pUndef, u = pUndef, lastU = pUndef, - Qn = pUndef, lastQn = pUndef, An = pUndef, lastAn = pUndef, - x = pUndef, y = pUndef, qn = pUndef, rn = pUndef; - - precision res = pnew(pparm(n)); /* default res is argument */ - - pm = pfactorbase(n, k, &m, aborts); /* m may have been reduced */ - - bsize = (m+2) * sizeof (SolnPtr); -#ifdef BWGC - b = (SolnPtr *) gc_malloc(bsize); -#else - b = (SolnPtr *) malloc(bsize); -#endif - if (b == (SolnPtr *) 0) goto nomem; - -#ifdef BWGC - e = (solnvec) gc_malloc((m+1) * sizeof e[0]); -#else - e = (solnvec) malloc((m+1) * sizeof e[0]); -#endif - if (e == (solnvec) 0) { -nomem: - errorp(PNOMEM, "pcfrac", "out of memory"); - goto bail; - } - - memset(b, '\0', bsize); /* F1: Initialize */ - if (maxCount != (unsigned *) 0) count = *maxCount; - cfracTsolns = cfracPsolns = cfracT2solns = cfracFsolns = cfracNabort = 0; - - eas = getEas(n, k, pm, m, aborts); /* early abort strategy */ - - if (verbose > 1) { - fprintf(stdout, "factorBase[%u]: ", m); - for (j = 0; j < m; j++) { - fprintf(stdout, "%u ", pm[j]); - } - putc('\n', stdout); - fflush(stdout); - } - - pset(&t, pmul(utop(k), n)); /* E1: Initialize */ - pset(&r, psqrt(t)); /* constant: sqrt(k*n) */ - pset(&twog, padd(r, r)); /* constant: 2*sqrt(k*n) */ - pset(&u, twog); /* g + Pn */ - pset(&lastU, twog); - pset(&Qn, pone); - pset(&lastQn, psub(t, pmul(r, r))); - pset(&An, pone); - pset(&lastAn, r); - pset(&qn, pzero); - - do { -F2: - do { - if (--count == 0) goto bail; - pset(&t, An); - pdivmod(padd(pmul(qn, An), lastAn), n, pNull, &An); /* (5) */ - pset(&lastAn, t); - - pset(&t, Qn); - pset(&Qn, padd(pmul(qn, psub(lastU, u)), lastQn)); /* (7) */ - pset(&lastQn, t); - - pset(&lastU, u); - - pset(&qn, pone); /* eliminate 40% of next divmod */ - pset(&rn, psub(u, Qn)); - if (pge(rn, Qn)) { - pdivmod(u, Qn, &qn, &rn); /* (4) */ - } - pset(&u, psub(twog, rn)); /* (6) */ - s = 1-s; - - e[0] = s; - i = pfactorQ(&t, Qn, pm, &e[1], m, eas); /* E3: Factor Qn */ - if (i < -1) cfracNabort++; - /* - * We should (but don't, yet) check to see if we can get a - * factor by a special property of Qn = 1 - */ - if (picmp(Qn, 1) == 0) { - errorp(PDOMAIN, "pcfrac", "cycle encountered; pick bigger k"); - goto bail; /* we ran into a cycle; give up */ - } - } while (i < 0); /* while not a solution */ - - pset(&x, An); /* End of Algorithm E; we now have solution: <x,t,e> */ - - if (i == 0) { /* if partial */ - if ((sp = findSoln(oddt, t)) == (SolnPtr) 0) { - cfracTsolns++; - if (verbose >= 2) putc('.', stderr); - if (verbose > 3) printSoln(stdout, "Partial: ","\n", pm,m,x,t,e); - oddt = newSoln(n, pm, m, oddt, x, t, e); - goto F2; /* wait for same t to occur again */ - } - if (verbose > 3) printSoln(stdout, "Partial: ", " -->\n", pm,m,x,t,e); - pset(&t, pone); /* take square root */ - combineSoln(&x, &t, e, pm, m, n, sp); - cfracT2solns++; - if (verbose) putc('#', stderr); - if (verbose > 2) printSoln(stdout, "PartSum: ", "", pm, m, x, t, e); - } else { - combineSoln(&x, &t, e, pm, m, n, (SolnPtr) 0); /* normalize */ - cfracPsolns++; - if (verbose) putc('*', stderr); - if (verbose > 2) printSoln(stdout, "Full: ", "", pm, m, x, t, e); - } - - /* - * Crude gaussian elimination. We should be more effecient about the - * binary vectors here, but this works as it is. - * - * At this point, t must be pone, or t occurred twice - * - * Loop Invariants: e[0:h] even - * t^2 is a product of squares of primes - * b[h]->e[0:h-1] even and b[h]->e[h] odd - */ - h = m+1; - do { - --h; - if (e[h]) { /* F3: Search for odd */ - bp=b[h]; - if (bp == (SolnPtr) 0) { /* F4: Linear dependence? */ - if (verbose > 3) { - printSoln(stdout, " -->\nFullSum: ", "", pm, m, x, t, e); - } - if (verbose > 2) putc('\n', stdout); - b[h] = newSoln(n, pm, m, bp, x, t, e); - goto F2; - } - combineSoln(&x, &t, e, pm, m, n, bp); - } - } while (h != 0); - /* - * F5: Try to Factor: We have a perfect square (has about 50% chance) - */ - cfracFsolns++; - pset(&y, t); /* t is already sqrt'd */ - - switch (verbose) { - case 0: break; - case 1: putc('/', stderr); break; - case 2: putc('\n', stderr); break; - default: ; - putc('\n', stderr); - printSoln(stdout, " -->\nSquare: ", "\n", pm, m, x, t, e); - fputs("x,y: ", stdout); - fputp(stdout, x); fputs(" ", stdout); - fputp(stdout, y); putc('\n', stdout); - fflush(stdout); - } - } while (peq(x, y) || peq(padd(x, y), n)); /* while x = +/- y */ - - pset(&res, pgcd(padd(x, y), n)); /* factor found at last */ - - /* - * Check for degenerate solution. This shouldn't happen. Detects bugs. - */ - if (peq(res, pone) || peq(res, n)) { - fputs("Error! Degenerate solution:\n", stdout); - fputs("x,y: ", stdout); - fputp(stdout, x); fputs(" ", stdout); - fputp(stdout, y); putc('\n', stdout); - fflush(stdout); - abort(); - } - -bail: - if (maxCount != (unsigned *) 0) *maxCount = count; - - if (b != (SolnPtr *) 0) for (j = 0; j <= m; j++) freeSoln(b[j]); - freeEas(eas); - freeSolns(oddt); -#ifndef IGNOREFREE - free(e); - free(pm); -#endif - - pdestroy(r); pdestroy(twog); pdestroy(u); pdestroy(lastU); - pdestroy(Qn); pdestroy(lastQn); pdestroy(An); pdestroy(lastAn); - pdestroy(x); pdestroy(y); pdestroy(qn); pdestroy(rn); - pdestroy(t); pdestroy(n); - - return presult(res); -} - -/* - * Initialization for pcfrac factoring method - * - * k - An integer multiplier to use for n (k must be < n) - * you can use findk to get a good value. k should be squarefree - * m - The number of primes to use in the factor base - * aborts - the number of early aborts to use - */ -int pcfracInit(m, k, aborts) - unsigned m; - unsigned k; - unsigned aborts; -{ - pcfrac_m = m; - pcfrac_k = k; - pcfrac_aborts = aborts; - return 1; -} diff --git a/src/benchmarks/cfrac/pcmp.c b/src/benchmarks/cfrac/pcmp.c deleted file mode 100644 index 2c8e0b8..0000000 --- a/src/benchmarks/cfrac/pcmp.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "pdefs.h" -#include "precision.h" - -/* - * Compare to zero (normalization not assumed) - * - * Returns same as pcmp(u, 0); - */ -int pcmpz(u) - register precision u; -{ - register digitPtr uPtr; - register int i; - - (void) pparm(u); - i = 0; - uPtr = u->value; - do { - if (*uPtr++ != 0) { - if (u->sign) i = -1; else i = 1; - break; - } - } while (uPtr < u->value + u->size); - - pdestroy(u); - return i; -} - -/* - * Compare u to v. - * - * Return: < 0 if u < v - * = 0 if u = v - * > 0 if u > v - * - * This routine is the one that assumes results are normalized! - * - no leading 0's - * - no negative 0 - */ -int pcmp(u, v) - precision u, v; -{ - register digitPtr uPtr, vPtr; - register int i; /* should be bigger than posit */ - - (void) pparm(u); - (void) pparm(v); - if (u->sign != v->sign) { - if (u->sign) i = -1; else i = 1; - } else { - i = u->size - v->size; - if (i == 0) { - uPtr = u->value + u->size; - vPtr = v->value + v->size; - do { - if (*--uPtr != *--vPtr) break; - } while (vPtr > v->value); - if (*uPtr > *vPtr) i = 1; - else if (*uPtr < *vPtr) i = -1; - } - - if (u->sign) i = -i; - } - - pdestroy(u); - pdestroy(v); - return i; -} diff --git a/src/benchmarks/cfrac/pconst.c b/src/benchmarks/cfrac/pconst.c deleted file mode 100644 index 89b63a7..0000000 --- a/src/benchmarks/cfrac/pconst.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "pdefs.h" - -static precisionType pzeroConst = { -#ifndef BWGC - (short) 1, /* refcount (read/write!) */ -#endif - (posit) 1, /* size */ - (posit) 1, /* digitcount */ - (boolean) 0, /* sign */ - { (digit) 0 } /* value */ -}; - -static precisionType poneConst = { -#ifndef BWGC - (short) 1, /* refcount (read/write!) */ -#endif - (posit) 1, /* size */ - (posit) 1, /* digitcount */ - (boolean) 0, /* sign */ - { (digit) 1 } /* value */ -}; - -static precisionType ptwoConst = { -#ifndef BWGC - (short) 1, /* refcount (read/write!) */ -#endif - (posit) 1, /* size */ - (posit) 1, /* digitcount */ - (boolean) 0, /* sign */ - { (digit) 2 } /* value */ -}; - -static precisionType p_oneConst = { -#ifndef BWGC - (short) 1, /* refcount (read/write!) */ -#endif - (posit) 1, /* size */ - (posit) 1, /* digitcount */ - (boolean) 1, /* sign */ - { (digit) 1 } /* value */ -}; - -precision pzero = &pzeroConst; /* zero */ -precision pone = &poneConst; /* one */ -precision ptwo = &ptwoConst; /* two */ -precision p_one = &p_oneConst; /* negative one */ diff --git a/src/benchmarks/cfrac/pcvt.h b/src/benchmarks/cfrac/pcvt.h deleted file mode 100644 index e2dd724..0000000 --- a/src/benchmarks/cfrac/pcvt.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Machine dependent file used for conversion routines - * (e.g. atop, ptoa, itop, ptoi, etc) - */ - -/* - * For pXtop: (X = {i,u,l,ul,d}) - */ -#define INTSIZE 2 /* floor(log[Base](2*(MAXINT+1))) */ -#define LONGSIZE 2 /* floor(log[Base](2*(MAXLONG+1))) */ -#define DOUBLESIZE 129 /* double precision size = log[base](HUGE) */ - -/* - * For ptoX - */ -#define MAXINT (int) ((unsigned int) ~0 >> 1) -#define MAXLONG (long) ((unsigned long) ~0 >> 1) -#define MAXUNSIGNED (~ (unsigned int) 0) -#define MAXUNSIGNEDLONG (~ (unsigned long) 0L) - -#define MAXACC (~ (accumulator) 0) - -/* - * aBase - Ascii base (ptoa) - * There are aDigits Ascii digits per precision digit, pDigits. - * At least one of { aDigits, pDigits } <= (MAXINT / the maximum posit value). - */ -#define aDigits 525 /* aDigits/pDigits >~= log[aBase](Base) */ -#define pDigits 109 /* 525/109=4.8165>log[10](65536)=4.816479931 */ -#define aBase 10 /* string conversion base */ -#define aDigit 1000000000 /* must be power of aBase < MAXINT */ -#define aDigitLog 9 /* log[aBase] of aDigit */ diff --git a/src/benchmarks/cfrac/pdefs.h b/src/benchmarks/cfrac/pdefs.h deleted file mode 100644 index 9c43099..0000000 --- a/src/benchmarks/cfrac/pdefs.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * +------------------------------------------------------------------+ - * | Private Math Library Definitions | - * +------------------------------------------------------------------+ - */ -/* - * Optional assembly language - */ -#ifdef ASM -#include "machineop.h" /* 16-bit integer machine operations */ -#define uModDiv(n, d, qp) umoddiv16(n, d, qp) /* slight help */ -#else -#define uModDiv(n, d, qp) (*(qp) = (n) / (d), (n) % (d)) -#endif -#define uMul(u, v) ((u) * (v)) /* fast enough */ - -/* - * Optional alternate memory allocator - */ - -#ifndef MYALLOC - -# if defined(BWGC) -extern char *gc_malloc_atomic(); -#define allocate(size) (char *) gc_malloc_atomic(size) -# elif defined(CUSTOM_MALLOC) -#define allocate(size) CUSTOM_MALLOC(size) -# else -/* extern char *malloc(); */ -#define allocate(size) (char *) malloc(size) -# endif - -#ifdef IGNOREFREE -#define deallocate(p) {}; -# elif defined(CUSTOM_FREE) -#define deallocate(p) CUSTOM_FREE(p) -#else -/* -extern int free(); -*/ -#define deallocate(p) free(p) -#endif - -#else -extern char *allocate(); -extern void deallocate(); -#endif - -/* - * These next four types are used only used in this include file - */ -#include <stdint.h> -typedef unsigned char u8; /* 8 bits */ -typedef uint16_t u16; /* 16 bits */ -typedef uint32_t u32; /* 32 bits */ -typedef u8 boolean; /* 1 bit */ - -#define BASE 65536 /* Base * (Base-1) <= MAXINT */ - -/* - * Operations on Base (unsigned math) - */ -#define modBase(u) ((u) & 0xffff) /* remainder on Base */ -#define divBase(u) ((u) >> 16) /* divide by Base */ -#define mulBase(u) ((u) << 16) /* multiply by Base */ - -/* - * The type of a variable used to store intermediate results. - * This should be the most efficient unsigned int on your machine. - */ -typedef u32 accumulator; /* 0..(Base * Base) - 1 */ - -/* - * The type of a single digit - */ -typedef u16 digit; /* 0..Base-1 */ - -/* - * The type of a digit index (the largest number of digits - 1) - * Determines the maximum representable precision (not usually changed) - */ -typedef u16 posit; /* 0..size */ - -typedef unsigned short prefc; /* in precision.h also */ -/* - * End of area which needs to be modified - */ - -#define false 0 -#define true 1 - -typedef digit digitString[1]; /* dummy array type */ -typedef digit *digitPtr; - -/* - * A normalized integer has the following attributes: - * -0 cannot occur - * all digits >= size assumed to be 0. (no leading zero's) - * size > 0 - */ -typedef struct { -#ifndef BWGC - prefc refcount; /* reference count (must be 1st [for pref]) */ -#endif - posit alloc; /* allocated size */ - posit size; /* number of digits */ - boolean sign; /* sign: TRUE negative */ - digitString value; -} precisionType; - -typedef precisionType *precision; - -/* - * Overlay for cache of precisions - */ -typedef struct { - precision next; /* next item in list */ - short count; /* number of items in this sublist */ -} cacheType; - -typedef cacheType *cachePtr; -/* - * Maximum total memory consumed by cache = - * LIMIT * (1 + SIZE * (PrecisionSize + sizeof(digit) * (SIZE-1) / 2)) - */ -#ifndef CACHESIZE -#define CACHESIZE 32 /* size of allocation cache */ -#endif -#define CACHELIMIT 128 /* Determines max mem used by cache */ - -#define PrecisionSize (sizeof(precisionType) - sizeof(digitString)) - -/* - * Function definitions are all in the global include file "mathdefs.h". - */ -extern precision palloc(); /* semi-private */ -extern int pfree(); /* semi-private */ -extern void pnorm(); /* semi-private */ diff --git a/src/benchmarks/cfrac/pdivmod.c b/src/benchmarks/cfrac/pdivmod.c deleted file mode 100644 index ce4a24b..0000000 --- a/src/benchmarks/cfrac/pdivmod.c +++ /dev/null @@ -1,315 +0,0 @@ -#include "pdefs.h" -#include "precision.h" - -#ifdef DEBUG -#include <stdio.h> -#endif - -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Divide u (dividend) by v (divisor); If non-null, qp and rp are set to - * quotient and remainder. The result returned will be *qp, unless qp is - * NULL, then *rp will be returned if non-null, otherwise pUndef is returned. - * - * Produce: - * - * q (quotient) = u div v (v != 0) - * truncation is toward zero - * - * r (remainder) = u mod v - * = u - u div v * v (v != 0) - * = u (v == 0) - * ( e.g. u == q*v + r ) - * remainder has same sign and dividend - * - * Note: this has opposite convention than the C standard div fuction, - * but the same convention of the typical C "/" operator - * It is also inconvienient for the mod function. - */ -/* - * This algorithm is taken almost verbatum from Knuth Vol 2. - * Please note the following trivial(?) array index - * transformations (since MSD to LSD order is reversed): - * - * q[0..m] to Q[0..m] thus q[i] == Q[m-i] - * r[1..n] R[0..n-1] r[i] == R[n+1-i] - * u[0..m+n] w[0..m+n] u[i] == w[m+n-i] - * v[1..n] x[0..n-1] v[i] == x[n-i] - * - * let N == n - 1 so that n == N + 1 thus: - * - * q[0..m] to Q[0..m] thus q[i] == Q[m-i] - * r[1..n] R[0..N] r[i] == R[N+2-i] - * u[0..m+n] w[0..m+N+1] u[i] == w[m+N+1-i] - * v[1..n] x[0..N] v[i] == x[N+1-i] - */ - -/* - * Note: Be very observent of the usage of uPtr, and vPtr. - * They are used to point to u, v, w, q or r as necessary. - */ -precision pdivmod(u, v, qp, rp) - precision u, v, *qp, *rp; -{ - register digitPtr uPtr, vPtr, qPtr, LastPtr; - - register accumulator temp; /* 0 <= temp < base^2 */ - register digit carry; /* 0 <= carry < 2 */ - register digit hi; /* 0 <= hi < base */ - - register posit n, m; - digit d; /* 0 <= d < base */ - digit qd; /* 0 <= qd < base */ -#ifdef DEBUG - int i; -#endif - - precision q, r, w; /* quotient, remainder, temporary */ - - n = v->size; /* size of v and r */ - - (void) pparm(u); - (void) pparm(v); - if (u->size < n) { - q = pUndef; - r = pUndef; - pset(&q, pzero); - pset(&r, u); - goto done; - } - - m = u->size - n; - - uPtr = u->value + m + n; - vPtr = v->value + n; - - q = palloc(m + 1); - if (q == pUndef) return q; - - q->sign = (u->sign != v->sign); /* can generate -0 */ - - r = palloc(n); - if (r == pUndef) { - pdestroy(q); - return r; - } - r->sign = u->sign; -/* - * watch out! does this function return: q=floor(a/b) or trunc(a/b)? - * it's currently the latter, but every mathmaticion I have talked to - * prefers the former so that a % b returns between 0 to b-1. The - * problem is that this is slower and disagrees with C common practice. - */ - qPtr = q->value + m + 1; - - if (n == 1) { - d = *--vPtr; /* d is only digit of v */ - if (d == 0) { /* divide by zero? */ - q = pnew(errorp(PDOMAIN, "pdivmod", "divide by zero")); - } else { /* single digit divide */ -#ifndef ASM_16BIT - vPtr = r->value + n; - hi = 0; /* hi is current remainder */ - do { - temp = mulBase(hi); /* 0 <= temp <= (base-1)^2 */ - temp += *--uPtr; /* 0 <= temp <= base(base-1) */ - hi = uModDiv(temp, d, --qPtr); /* 0 <= hi < base */ - } while (uPtr > u->value); - *--vPtr = hi; -#else - qPtr -= m + 1; - *(r->value) = memdivw1(qPtr, u->value, m + 1, d); -#endif - } - } else { /* muti digit divide */ - /* - * normalize: multiply u and v by d so hi digit of v > b/2 - */ - d = BASE / (*--vPtr+1); /* high digit of v */ - - w = palloc(n); /* size of v */ - if (w == pUndef) return w; - -#ifndef ASM_16BIT - vPtr = v->value; - uPtr = w->value; /* very confusing. just a temp */ - LastPtr = vPtr + n; - hi = 0; - do { /* single digit multiply */ - temp = uMul(*vPtr++, d); /* 0<= temp <= base(base-1)/2 */ - temp += hi; /* 0 <= temp <= (base^2-1)/2 */ - hi = divBase(temp); /* 0 <= hi < base / 2 */ - *uPtr++ = modBase(temp); /* 0 <= hi < base / 2 */ - } while (vPtr < LastPtr); /* on exit hi == 0 */ -#else - hi = memmulw1(w->value, v->value, n, d); -#endif - - pset(&v, w); - pdestroy(w); - - w = palloc(m + n + 1); - if (w == pUndef) return w; - -#ifndef ASM_16BIT - uPtr = u->value; - vPtr = w->value; /* very confusing. just a temp */ - LastPtr = uPtr + m + n; - do { /* single digit multiply */ - temp = uMul(*uPtr++, d); - temp += hi; - hi = divBase(temp); - *vPtr++ = modBase(temp); - } while (uPtr < LastPtr); - *vPtr = hi; /* note extra digit */ -#else - hi = memmulw1(w->value, u->value, m + n, d); - w->value[m + n] = hi; -#endif - - pset(&u, w); - pdestroy(w); - -#ifdef DEBUG - printf("m = %d n = %d\nd = %d\n", m, n, d); - printf("norm u = "); pshow(u); - printf("norm v = "); pshow(v); -#endif - - uPtr = u->value + m + 1; /* current least significant digit */ - do { - --uPtr; -#ifdef DEBUG - printf(" u = "); - for (i = n; i >= 0; --i) printf("%.*x ", sizeof(digit) * 2, uPtr[i]); - putchar('\n'); - printf(" v = "); - for (i = 1; i < 3; i++) printf("%.*x ", sizeof(digit) * 2, - v->value[n-i]); - putchar('\n'); -#endif -#ifndef ASM_16BIT - vPtr = v->value + n; - LastPtr = uPtr + n; - if (*LastPtr == *--vPtr) { /* guess next digit */ - qd = BASE - 1; - } else { - temp = mulBase(*LastPtr); - temp += *--LastPtr; /* 0 <= temp< base^2 */ - temp = uModDiv(temp, *vPtr, &qd); - --vPtr; - --LastPtr; - while (uMul(*vPtr, qd) > mulBase(temp) + *LastPtr) { - --qd; - temp += vPtr[1]; - if (temp >= BASE) break; /* if so, vPtr*qd <= temp*base */ - } - LastPtr += 2; - } - /* - * Single digit Multiply then Subtract - */ - vPtr = v->value; - carry = 1; /* noborrow bit */ - hi = 0; /* hi digit of multiply */ - do { - /* multiply */ - temp = uMul(qd, *vPtr++); /* 0 <= temp <= (base-1)^2 */ - temp += hi; /* 0 <= temp <= base(base-1) */ - hi = divBase(temp); - temp = modBase(temp); - /* subtract */ - temp = (BASE-1) - temp; /* 0 <= temp < base */ - temp += *uPtr + carry; /* 0 <= temp < 2*base */ - carry = divBase(temp); - *uPtr++ = modBase(temp); /* 0 <= carry < 2 */ - } while (uPtr < LastPtr); - temp = (BASE-1) - hi; - temp += *uPtr + carry; - carry = divBase(temp); - *uPtr = modBase(temp); - uPtr -= n; -#else -#if 0 - carry = !memmulsubw(uPtr, v->value, n, qd); /* 1 if noborrow */ -#endif - carry = !memdivw(uPtr, v->value, n, &qd); /* 1 if noborrow */ -#endif -#ifdef DEBUG - printf(" qhat = %.*x\n", sizeof(digit) * 2, qd); - printf(" new u = "); - for (i = n; i >= 0; --i) printf("%.*x ", sizeof(digit) * 2, uPtr[i]); - putchar('\n'); -#endif - if (carry == 0) { /* Test remainder, add back */ - vPtr = v->value; - LastPtr = uPtr + n; - do { - temp = *uPtr + *vPtr++; - temp += carry; - carry = divBase(temp); - *uPtr++ = modBase(temp); - } while (uPtr < LastPtr); - *uPtr += carry - BASE; /* real strange but works */ - uPtr -= n; - --qd; -#ifdef DEBUG - printf(" decrementing q...adding back\n"); - printf(" fixed u = "); - for (i = n; i >= 0; --i) printf("%.*x ", sizeof(digit) * 2, uPtr[i]); - putchar('\n'); - printf(" newq = %.*x\n", sizeof(digit) * 2, qd); -#endif - } - *--qPtr = qd; /* one leading zero possible */ -#ifdef DEBUG - putchar('\n'); -#endif - } while (uPtr > u->value); - - /* - * Un-normalize to get remainder - */ -#ifndef ASM_16BIT - uPtr = u->value + n; /* skip hi digit (it's zero) */ - vPtr = r->value + n; - hi = 0; /* hi is current remainder */ - do { /* single digit divide */ - temp = mulBase(hi); /* 0<=temp < base^2-(base-1) */ - temp += *--uPtr; /* 0 <= temp < base^2 */ - hi = uModDiv(temp, d, --vPtr); - } while (uPtr > u->value); /* carry will be zero */ -#else - carry = memdivw1(r->value, u->value, n, d); /* always 0 */ -#endif - pnorm(r); /* remainder may have many leading 0's */ - } - - if (m > 0 && qPtr[m] == 0) { - --(q->size); /* normalize */ - } - if (q->size == 1 && *qPtr == 0) q->sign = false; - -done: - - pdestroy(u); - pdestroy(v); - - if (rp == (precision *) -1) { - if (qp != pNull) pset(qp, q); - pdestroy(q); - return presult(r); - } else if (qp == (precision *) -1) { - if (rp != pNull) pset(rp, r); - pdestroy(r); - return presult(q); - } - if (qp != pNull) pset(qp, q); - if (rp != pNull) pset(rp, r); - pdestroy(q); - pdestroy(r); - return pUndef; -} diff --git a/src/benchmarks/cfrac/pfactor.c b/src/benchmarks/cfrac/pfactor.c deleted file mode 100644 index 6c765d1..0000000 --- a/src/benchmarks/cfrac/pfactor.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdio.h> -#include "precision.h" -#include "pfactor.h" - -void showfactors(); - - -int main(argc, argv) - int argc; - char *argv[]; -{ - precision n = pUndef; - - --argc; - if (argc != 0) { - do { - pset(&n, atop(*++argv)); - showfactors(n); - } while (--argc > 0); - } else { - do { - pset(&n, fgetp(stdin)); - if (n == pUndef) break; - showfactors(n); - } while (1); - } - pdestroy(n); - return 0; -} - -void showfactors(n) - precision n; -{ - precision r = pUndef; - FactorList factors = (FactorList) 0; - - (void) pparm(n); - pset(&r, ptrial(n, (unsigned *) 0, &factors)); - fputp(stdout, n); - fputs(" = ", stdout); - pputfactors(stdout, factors); - if pne(r, pone) { - if pne(r, n) putc('*', stdout); - if (!pprime(r, 16)) { - fputc('(', stdout); fputp(stdout, r); fputc(')', stdout); - } else { - fputp(stdout, r); - } - } - putc('\n', stdout); - - pfreefactors(&factors); - pdestroy(r); - pdestroy(n); -} diff --git a/src/benchmarks/cfrac/pfactor.h b/src/benchmarks/cfrac/pfactor.h deleted file mode 100644 index edd5686..0000000 --- a/src/benchmarks/cfrac/pfactor.h +++ /dev/null @@ -1,62 +0,0 @@ -typedef struct Pfs { - struct Pfs *next; - precision factor; - unsigned count; -} Pfactor; - -typedef Pfactor *FactorPtr; -typedef FactorPtr FactorList; -typedef precision (*pfunc)(); /* pointer to func returning precision */ - -#ifndef __STDC__ - -extern int pprime(); /* test whether a number is prime */ -extern precision pnextprime(); /* next prime >= it's argument */ - -extern precision pgcd(); /* greatest common divisor */ -extern precision plcm(); /* least common multiple */ -extern precision peuclid(); /* extended euclid's algorithm */ - -extern precision prho(); /* find factor using rho method */ -extern precision pfermat(); /* find factor using Fermat's method */ -extern precision pcfrac(); /* factor w/continued fractions */ - -extern int prhoInit(); /* alter parameters for rho method */ -extern int pcfracInit(); /* alter paramteres for cfrac method */ - -extern precision ptrial(); /* find factors using trial division */ -extern precision prfactor(); /* recursively factor a number */ - -extern void paddfactor(); /* add a factor to a factorlist */ -extern void pputfactors(); /* print a factorlist */ -extern void pfreefactors(); /* return a factorlist to memory */ - -#else - -extern int pprime(precision, unsigned trialCount); -extern precision pnextprime(precision, unsigned trialCount); - -extern precision pgcd(precision, precision); -extern precision plcm(precision, precision); -extern precision peuclid(precision, precision, precision *, precision *); - -extern precision prho(precision n, unsigned *maxCount); -extern precision pfermat(precision n, unsigned *maxCount); -extern precision pcfrac(precision n, unsigned *maxCount); - -extern int prhoInit(precision c, unsigned batchSize); -extern int pcfracInit(unsigned m, unsigned k, unsigned aborts); - -extern precision ptrial(precision n, unsigned *maxCount, FactorList *); -extern precision prfactor(precision, unsigned *maxCount, pfunc, FactorList *); - -extern void paddfactor(FactorList *, precision); -extern void pfreefactors(FactorList *); - -#ifndef BUFSIZE -#include <stdio.h> -#endif - -extern void pputfactors(FILE *, FactorList); - -#endif diff --git a/src/benchmarks/cfrac/pfloat.c b/src/benchmarks/cfrac/pfloat.c deleted file mode 100644 index 63f4344..0000000 --- a/src/benchmarks/cfrac/pfloat.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * High Precision Math Library Supplement for floating point routines - */ -#include <stdio.h> -#include <math.h> -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -extern precision palloc(); - -/* - * double to precision - */ -precision dtop(f) - register double f; -{ - register digitPtr uPtr; - register precision u; - - u = palloc(DOUBLESIZE); /* pretty big */ - if (u == pUndef) return u; - - if (f < 0.0) { - f = -f; - u->sign = true; - } else { - u->sign = false; - } - uPtr = u->value; - do { - *uPtr++ = fmod(f, (double) BASE); - f = floor(f / (double) BASE); - } while (f != 0.0); - - u->size = (uPtr - u->value); - - return presult(u); -} - -/* - * precision to double (no overflow check) - */ -double ptod(u) - precision u; -{ - register digitPtr uPtr; - register double f; - - (void) pparm(u); - uPtr = u->value + u->size; - f = 0.0; - do { - f = f * (double) BASE + (double) *--uPtr; - } while (uPtr > u->value); - - if (u->sign) f = -f; - - pdestroy(u); - return f; -} diff --git a/src/benchmarks/cfrac/pgcd.c b/src/benchmarks/cfrac/pgcd.c deleted file mode 100644 index a72a8a7..0000000 --- a/src/benchmarks/cfrac/pgcd.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "precision.h" - -/* - * Euclid's Algorithm - * - * Given u and v, calculated and return their greatest common divisor. - */ -precision pgcd(u, v) - precision u, v; -{ - precision u3 = pnew(pabs(pparm(u))), v3 = pnew(pabs(pparm(v))); - precision q = pUndef, r = pUndef; - - while (pnez(v3)) { - pdivmod(u3, v3, &q, &r); - pset(&u3, v3); - pset(&v3, r); - } - - pdestroy(v3); - pdestroy(q); pdestroy(r); - pdestroy(u); pdestroy(v); - return presult(u3); /* result always positive */ -} diff --git a/src/benchmarks/cfrac/phalf.c b/src/benchmarks/cfrac/phalf.c deleted file mode 100644 index 8658de5..0000000 --- a/src/benchmarks/cfrac/phalf.c +++ /dev/null @@ -1,36 +0,0 @@ -#include <string.h> -#include "pdefs.h" -#include "precision.h" - -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Divide a precision by 2 - */ -precision phalf(u) - register precision u; -{ -#ifdef ASM_16BIT - register precision w; - register posit usize; - - pparm(u); - usize = u->size; - w = palloc(usize); - if (w == pUndef) return w; - - w->sign = u->sign; - (void) memcpy(w->value, u->value, usize * sizeof(digit)); - - memlsrw(w->value, usize); /* 68000 assembly language routine */ - if (usize > 1 && w->value[usize-1] == (digit) 0) { /* normalize */ - --(w->size); - } - pdestroy(u); - return presult(w); -#else - return pdiv(u, ptwo); -#endif -} diff --git a/src/benchmarks/cfrac/picmp.c b/src/benchmarks/cfrac/picmp.c deleted file mode 100644 index b942268..0000000 --- a/src/benchmarks/cfrac/picmp.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "pdefs.h" -#include "precision.h" - -static char cmpError[] = "Second arg not single digit"; - -/* - * Single-digit compare - */ -int picmp(u, v) - register precision u; - register int v; -{ - register int i; - - (void) pparm(u); - - if (u->sign) { - i = -1; - if (v < 0) { - if (-v >= BASE) { - errorp(PDOMAIN, "picmp", cmpError); - } - if (u->size == 1) { - i = - (int) *(u->value) - v; - } - } - } else { - i = 1; - if (v >= 0) { - if (v >= BASE) { - errorp(PDOMAIN, "picmp", cmpError); - } - if (u->size == 1) { - i = (int) *(u->value) - v; - } - } - } - - pdestroy(u); - return i; -} diff --git a/src/benchmarks/cfrac/pidiv.c b/src/benchmarks/cfrac/pidiv.c deleted file mode 100644 index 61c09a7..0000000 --- a/src/benchmarks/cfrac/pidiv.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "pdefs.h" -#include "precision.h" -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Single-digit divide - */ -precision pidiv(u, v) - register precision u; - int v; -{ -#ifndef ASM_16BIT - register digitPtr uPtr, qPtr; - register accumulator temp; /* 0 <= temp < base^2 */ -#endif - register digit r, d; /* 0 <= r,d < base */ - register posit m; - register precision q; - - (void) pparm(u); - - if (v < 0) d = (digit) -v; else d = (digit) v; - if (d >= BASE) { - q = pnew(errorp(PDOMAIN, "pidiv", "divisor too big for single digit")); - goto done; - } - if (d == 0) { - q = pnew(errorp(PDOMAIN, "pidiv", "divide by zero")); - goto done; - } - m = u->size; - q = palloc(m); - if (q == pUndef) goto done; - -#ifndef ASM_16BIT - qPtr = q->value + m; - uPtr = u->value + m; - r = 0; /* r is current remainder */ - do { - temp = mulBase(r); /* 0 <= temp <= (base-1)^2 */ - temp += *--uPtr; /* 0 <= temp <= base(base-1) */ - r = uModDiv(temp, d, --qPtr); /* 0 <= r < base */ - } while (uPtr > u->value); -#else - r = memdivw1(q->value, u->value, m, d); -#endif - /* - * normalize q - */ - if (m > 1 && q->value[m-1] == 0) { - --(q->size); - } - q->sign = (u->sign != (v < 0)); - if (q->size == 1 && *(q->value) == 0) q->sign = false; -done: - pdestroy(u); - return presult(q); -} diff --git a/src/benchmarks/cfrac/pimod.c b/src/benchmarks/cfrac/pimod.c deleted file mode 100644 index b26536d..0000000 --- a/src/benchmarks/cfrac/pimod.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "pdefs.h" -#include "precision.h" -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Single-digit remainder - */ -int pimod(u, v) - register precision u; - int v; -{ -#ifndef ASM_16BIT - register digitPtr uPtr; - register accumulator temp; /* 0 <= temp < base^2 */ -#endif - register digit r = 0, d; /* 0 <= r,d < base */ - register int res = 0; - - (void) pparm(u); - if (v < 0) d = (digit) -v; else d = (digit) v; - if (d >= BASE) { - errorp(PDOMAIN, "pimod", "divisor too big for single digit"); - goto done; - } - if (d == 0) { - errorp(PDOMAIN, "pimod", "divide by zero"); - goto done; - } -#ifndef ASM_16BIT - uPtr = u->value + u->size; - r = 0; /* r is current remainder */ - do { - temp = mulBase(r); /* 0 <= temp <= (base-1)^2 */ - temp += *--uPtr; /* 0 <= temp <= base(base-1) */ - r = temp % d; /* 0 <= r < base */ - } while (uPtr > u->value); -#else - r = memmodw1(u->value, u->size, d); -#endif - - res = (int) r; - if (u->sign) res = -res; -done: - pdestroy(u); - return res; -} diff --git a/src/benchmarks/cfrac/pio.c b/src/benchmarks/cfrac/pio.c deleted file mode 100644 index 16b5bda..0000000 --- a/src/benchmarks/cfrac/pio.c +++ /dev/null @@ -1,165 +0,0 @@ -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Output a string to a file. - * - * Returns: - * the number of characters written - * or EOF if error - */ -static int fouts(stream, chp) - FILE *stream; - register char *chp; -{ - register int count = 0, res = 0; - - if (chp != (char *) 0 && *chp != '\0') do { - count++; - res = putc(*chp, stream); - } while (*++chp != '\0' && res != EOF); - - if (res != EOF) res = count; - return res; -} - -/* - * output the value of a precision to a file (no cr or whitespace) - * - * Returns: - * The number of characters output or EOF if error - */ -int fputp(stream, p) - FILE *stream; - precision p; -{ - int res; - char *chp = ptoa(pparm(p)); - - res = fouts(stream, chp); - deallocate(chp); - pdestroy(p); - return res; -} - -/* - * Output a precision to stdout with a newline (useful from debugger) - */ -int putp(p) - precision p; -{ - int res; - char *chp = ptoa(pparm(p)); - - res = fouts(stdout, chp); - res = putc('\n', stdout); - deallocate(chp); - pdestroy(p); - return res; - -} - -/* - * Output a justified precision - * - * Returns: The number of characters in the precision, or EOF if error - */ -int fprintp(stream, p, minWidth) - FILE *stream; - precision p; - register int minWidth; -{ - int res; - char *chp = ptoa(pparm(p)); - int len; - - len = strlen(chp); - if (minWidth < 0) { /* left-justified */ - res = fouts(stream, chp); - while (minWidth++ < -len) { - putc(' ', stream); - } - } else { - while (minWidth-- > len) { /* right-justified */ - putc(' ', stream); - } - res = fouts(stream, chp); - } - - deallocate(chp); - pdestroy(p); - return res; -} - - -/* - * Read in a precision type - same as atop but with io - * - * leading whitespace skipped - * an optional leading '-' or '+' followed by digits '0'..'9' - * leading 0's Ok - * stops at first unrecognized character - * - * Returns: pUndef if EOF or invalid argument (NULL or nondigit as 1st digit) - */ -precision fgetp(stream) - FILE *stream; -{ - precision res = pUndef; - precision clump = pUndef; - int sign = 0; - register int ch; - register accumulator temp, x; - register int j; - - ch = getc(stream); - if (ch != EOF) { - while (isspace(ch)) ch = getc(stream); /* skip whitespace */ - if (ch == '-') { - sign = 1; - ch = getc(stream); - } else if (ch == '+') { - ch = getc(stream); - } - if (isdigit(ch)) { - pset(&res, pzero); - pset(&clump, utop(aDigit)); - do { - j = aDigitLog-1; - temp = ch - '0'; - do { - if (!isdigit(ch = getc(stream))) goto atoplast; - temp = temp * aBase + (ch - '0'); - } while (--j > 0); - pset(&res, padd(pmul(res, clump), utop(temp))); - } while (isdigit(ch = getc(stream))); - goto atopdone; -atoplast: - x = aBase; - while (j++ < aDigitLog-1) { - x *= aBase; - } - pset(&res, padd(pmul(res, utop(x)), utop(temp))); -atopdone: - if (ch != EOF) ungetc(ch, stream); - if (sign) { - pset(&res, pneg(res)); - } - } else { - if (ch == EOF) { - res = pUndef; - } else { - ungetc(ch, stream); - } - } - } else { - res = pUndef; - } - pdestroy(clump); - if (res == pUndef) return res; - return presult(res); -} diff --git a/src/benchmarks/cfrac/pmul.c b/src/benchmarks/cfrac/pmul.c deleted file mode 100644 index e69a366..0000000 --- a/src/benchmarks/cfrac/pmul.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "pdefs.h" -#include "precision.h" -#include <string.h> - -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Multiply u by v (assumes normalized) - */ -precision pmul(u, v) - register precision v; /* register a5 on 68000 */ -#ifdef ASM_16BIT - register precision u; /* register a4 */ -{ -#else - precision u; -{ - digitPtr vPtr; - register digitPtr uPtr, wPtr, HiDigit; - register accumulator temp; /* 0 <= temp < base * base */ /* d7 */ - register digit vdigit; /* d6 */ -#endif - register digit hi; /* 0 <= hi < base */ /* d5 */ - precision w; - - (void) pparm(u); - (void) pparm(v); - /* - * Check for multiply by zero. Helps prevent wasted storage and -0 - */ - if (peqz(u) || peqz(v)) { - w = palloc(1); - if (w == pUndef) return w; - - w->sign = false; - w->value[0] = 0; - } else { - if (u->size < v->size) { /* u is biggest number (for inner loop speed) */ - w = u; u = v; v = w; - } - - w = palloc(u->size + v->size); - if (w == pUndef) return w; - - w->sign = (u->sign != v->sign); - -#ifndef ASM_16BIT - uPtr = u->value; - vPtr = v->value; - wPtr = w->value + u->size; /* this is correct! */ - do { - *--wPtr = 0; - } while (wPtr > w->value); - - vPtr = v->value; - HiDigit = u->value + u->size; - do { - uPtr = u->value; - wPtr = w->value + (vPtr - v->value); - hi = 0; - vdigit = *vPtr; - do { - temp = uMul(vdigit, *uPtr++); /* 0 <= temp <= (base-1)^2 */ - temp += *wPtr; /* 0 <= temp <= base(base-1) */ - temp += hi; /* 0 <= temp < base * base */ - hi = divBase(temp); /* 0 <= hi < base */ - *wPtr++ = modBase(temp); - } while (uPtr < HiDigit); - *wPtr++ = hi; - } while (++vPtr < v->value + v->size); -#else - hi = memmulw(w->value, u->value, u->size, v->value, v->size); -#endif - if (hi == 0) { - --(w->size); /* normalize */ - } - } - - pdestroy(u); - pdestroy(v); - return presult(w); -} diff --git a/src/benchmarks/cfrac/pneg.c b/src/benchmarks/cfrac/pneg.c deleted file mode 100644 index c781066..0000000 --- a/src/benchmarks/cfrac/pneg.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "pdefs.h" /* private include file */ -#include "precision.h" /* public include file for forward refs */ -#include <string.h> - -/* - * negation - */ -precision pneg(u) - register precision u; -{ - precision w; - - (void) pparm(u); - w = palloc(u->size); - if (w == pUndef) return w; - - w->sign = u->sign; - if (pnez(u)) { /* don't create a negative 0 */ - w->sign = !w->sign; - } - (void) memcpy(w->value, u->value, u->size * sizeof(digit)); - - pdestroy(u); - return presult(w); -} diff --git a/src/benchmarks/cfrac/podd.c b/src/benchmarks/cfrac/podd.c deleted file mode 100644 index def95b4..0000000 --- a/src/benchmarks/cfrac/podd.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "pdefs.h" -#include "precision.h" - -/* - * Returns non-zero if u is odd - */ -int podd(u) - precision u; -{ - register int res; - - (void) pparm(u); - res = (*(u->value) & 1); - pdestroy(u); - return res; -} diff --git a/src/benchmarks/cfrac/pops.c b/src/benchmarks/cfrac/pops.c deleted file mode 100644 index 7154dd7..0000000 --- a/src/benchmarks/cfrac/pops.c +++ /dev/null @@ -1,339 +0,0 @@ -#ifdef DEBUGOPS -#include <stdio.h> -#endif -/* - * High Precision Math Library - * - * Written by Dave Barrett 2/23/83 - * Translated from modcal to pascal 4/30/84 - * Mod portability fixed; removed floor function 5/14/84 - * Fixed numerous bugs and improved robustness 5/21/84 - * Translated to C 6/14/84 - * Changed precision to be determined at run-time 5/19/85 - * Added dynamic allocation 7/21/85 - * Combined unsigned math and integer math 8/01/85 - * Fixed Bug in pcmp 7/20/87 - * Fixed handling of dynamic storage (refcount added) 7/20/87 - * Final debugging of current version 8/22/87 - * Fixed many bugs in various routines, wrote atop 2/07/89 - * Tuned for speed, fixed overflow problems 3/01/89 - * Removed refcounts, more tuning, removed pcreate 3/16/89 - * Added cmp macros, change name of pzero, added pshift 4/29/89 - * Repaired operation order bugs in pdiv, calc.c 5/15/91 - * Added pdiv macro, split out pcmp, pabs, much cleanup 5/21/91 - * - * warning! The mod operation with negative arguments not portable. - * I have therefore avoided it completely with much pain. - * - * The following identities have proven useful: - * - * given: a % b = a - floor(a/b) * b - * then : -a % -b = -(a % b) - * -a % b = -( a % -b) = b - a % b (a % b != 0) - * a % -b = -(-a % b) = a % b - b (a % b != 0) - * - * given: a % b = a - a / b * b - * then : -a % -b = -a % b = -(a % b) - * a % -b = a % b - * - * Also, be very careful of computations in the inner loops. Much - * work has been done to make sure the compiler does not re-arrange - * expressions to cause an overflow. The compiler may still be doing - * unnecessary type conversions. - * - * NOTES: - * - * The ptoa routine creates storage which is likely to be forgotton. - * - * A function returning a result must use the result. If it doesn't - * the storage is never freed. For example: itop(2); by itself - * You must make sure to pdestroy the result. - * - * An error (out of storage) fails to deallocate u and v. - * - * psub, pcmp, pdiv, and pmul all assume normalized arguments. - * - * This file contains the storage management-specific code: - * palloc, pfree, pset -- together these account for 45% of execution time - */ -#include <string.h> -#include "pdefs.h" /* private include file */ -#include "precision.h" /* public include file for forward refs */ - -cacheType pcache[CACHESIZE]; -static char ident[] = - " @(#) libprecision.a version 2.00 3-May-91 by Dave Barrett\n"; - -/* - * normalize (used by div and sub) - * remove all leading zero's - * force positive sign if result is zero - */ -void pnorm(u) - register precision u; -{ - register digitPtr uPtr; - - uPtr = u->value + u->size; - do { - if (*--uPtr != 0) break; - } while (uPtr > u->value); - - if (uPtr == u->value && *uPtr == 0) u->sign = false; - - u->size = (uPtr - u->value) + 1; /* normalize */ -} - -/* - * Create a number with the given size (private) (very heavily used) - */ -precision palloc(size) - register posit size; -{ - register precision w; - register cacheType *kludge = pcache + size; /* for shitty compilers */ - -#if !(defined(NOMEMOPT) || defined(BWGC)) - if (size < CACHESIZE && (w = kludge->next) != pUndef) { - kludge->next = ((cacheType *) w)->next; - --kludge->count; - } else { -#endif - w = (precision) allocate(PrecisionSize + sizeof(digit) * size); - if (w == pUndef) { - w = errorp(PNOMEM, "palloc", "out of memory"); - return w; - } -#if !(defined(NOMEMOPT) || defined(BWGC)) - } -#endif -#ifndef BWGC - w->refcount = 1; -#endif - w->size = w->alloc = size; -#ifdef DEBUGOPS - printf("alloc %.8x\n", w); - fflush(stdout); -#endif - return w; -} - -/* - * (Very heavily used: Called conditionally pdestroy) - * (should be void, but some compilers can't handle it with the macro) - */ -int pfree(u) - register precision u; -{ - register posit size; - register cacheType *kludge; /* for shitty compilers */ - -#ifdef DEBUGOPS - printf("free %.8x\n", u); - fflush(stdout); -#endif - - size = u->alloc; - - kludge = pcache + size; -#if !(defined(NOMEMOPT) || defined(BWGC)) - if (size < CACHESIZE && kludge->count < CACHELIMIT) { - ((cacheType *) u)->next = kludge->next; - kludge->next = u; - kludge->count++; - } else { -#endif - deallocate(u); -#if !(defined(NOMEMOPT) || defined(BWGC)) - } -#endif - return 0; -} - -/* - * User inteface: - * - * Rules: - * a precision must be initialized to pUndef or to result of pnew. - * a precision pointer must point to a precision or be pNull - * pUndef may not be passed as an rvalue into a function - * pNull may not be passed as an lvalue into a function - * - * presult and pdestroy are the only functions which may be passed pUndef - */ - -/* - * assignment with verification (slower, but helpful for bug detect) - * It would be nice if this routine could detect pointers to incorrect - * or non-living areas of memory. - * - * We can't check for undefined rvalue because we want to allow functions - * to return pUndef, and then let the application check for it after assigning - * it to a variable. - * - * usage: pset(&i, j); - */ -precision psetv(up, v) - register precision *up, v; -{ - register precision u; - -#ifdef DEBUGOPS - printf("psetv %.8x %.8x ", up, v); -#endif -#ifdef DEBUGOPS -#ifndef BWGC - printf("->%u", v->refcount); -#endif -#endif - if (up == pNull) { - errorp(PDOMAIN, "pset", "lvalue is pNull"); - } - u = *up; -#ifdef DEBUGOPS - printf(" %.8x", u); -#endif - *up = v; - if (v != pUndef) { -#ifndef BWGC - v->refcount++; -#endif - } - if (u != pUndef) { - if (u->sign & ~1) { /* a minimal check */ - errorp(PDOMAIN, "pset", "invalid precision"); - } -#ifndef BWGC - if (--(u->refcount) == 0) { -#ifdef DEBUGOPS - printf("->%u", u->refcount); -#endif - pfree(u); - } -#endif - } -#ifdef DEBUGOPS - putchar('\n'); - fflush(stdout); -#endif - return v; -} - -precision pparmv(u) - register precision u; -{ -#ifdef DEBUGOPS - printf("pparm %.8x\n", u); - fflush(stdout); -#endif - if (u == pUndef) { - errorp(PDOMAIN, "pparm", "undefined function argument"); - } - if (u->sign & ~1) { /* a minimal check */ - errorp(PDOMAIN, "pparm", "invalid precision"); - } -#ifndef BWGC - u->refcount++; -#endif - return u; -} - -/* - * Function version of unsafe pparmq macro - */ -precision pparmf(u) - register precision u; -{ -#ifndef BWGC - if (u != pUndef) { - u->refcount++; - } -#endif - return u; -} - -/* - * Function version of pdestroy macro - */ -void pdestroyf(u) - register precision u; -{ -#ifndef BWGC - if (u != pUndef && --u->refcount == 0) { - pfree(u); - } -#endif -} - -#ifndef __GNUC__ /* inline in header file */ -/* - * We cannot allow this to be a macro because of the probability that it's - * argument will be a function (e.g. utop(2)) - */ -precision pnew(u) - register precision u; -{ -#ifndef BWGC - u->refcount++; -#endif - return u; -} - -/* - * Cannot be a macro because of function argument possibility - */ -precision presult(u) - register precision u; -{ -#ifndef BWGC - if (u != pUndef) { - --(u->refcount); - } -#endif - return u; -} - -/* - * Quick but dangerous assignment - * - * Assumes: target not pNull and source not pUndef - */ -precision psetq(up, v) - register precision *up, v; -{ - register precision u = *up; /* up may NOT be pNULL! */ - - *up = v; /* up may be &v, OK */ -#ifndef BWGC - if (v != pUndef) { /* to allow: x=func(); if (x==pUndef) ... */ - v->refcount++; - } - if (u != pUndef && --(u->refcount) == 0) { - pfree(u); - } -#endif - return v; -} -#endif - -#if 0 /* original assignment code */ -precision pset(up, v) - register precision *up, v; -{ - register precision u; - -#ifndef BWGC - if (v != pUndef) v->refcount++; -#endif - if (up == pNull) { /* useful voiding parameters (pdiv) */ - pdestroy(v); - return pUndef; - } - u = *up; - if (u != pUndef) { /* useful to force initial creation */ - pdestroy(u); - } - *up = v; /* notice that v may be pUndef which is OK! */ - return v; /* no presult! This is a variable */ -} -#endif diff --git a/src/benchmarks/cfrac/ppowmod.c b/src/benchmarks/cfrac/ppowmod.c deleted file mode 100644 index 4528db9..0000000 --- a/src/benchmarks/cfrac/ppowmod.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "precision.h" - -/* - * Raise to precision power mod m - */ -precision ppowmod(u, v, m) - precision u, v, m; -{ - precision j = pUndef, i = pUndef, n = pUndef; - - (void) pparm(m); - pset(&i, pparm(u)); - pset(&n, pparm(v)); - pset(&j, pone); - - do { - if (podd(n)) { - pset(&j, pmod(pmul(i, j), m)); - } - pset(&n, phalf(n)); - if (peqz(n)) break; - pset(&i, pmod(pmul(i, i), m)); - } while (1); - - pdestroy(i); pdestroy(n); - pdestroy(u); pdestroy(v); pdestroy(m); - return presult(j); -} diff --git a/src/benchmarks/cfrac/precision.h b/src/benchmarks/cfrac/precision.h deleted file mode 100644 index 28befce..0000000 --- a/src/benchmarks/cfrac/precision.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Arbitrary precision integer math package - * - * (c) Copyright 1991 by David A. Barrett (barrett@asgard.UUCP) - * - * Not to be used for profit or distributed in systems sold for profit - */ - - -/* BEGIN EDB */ - -#include <stdlib.h> - -#if defined(USE_LOCH) && defined(_WIN32) -#pragma comment(lib, "loch.lib") -#endif - -#define NOMEMOPT 1 - -/* END EDB */ - -#ifndef BASE -typedef unsigned short prefc; /* reference counter type */ -typedef prefc *precision; /* this a a private data structure */ -extern int pfree(); /* free (private) */ -#endif - -typedef precision *pvector; /* a vector of precision */ -typedef pvector *parray; /* 2d array */ - -/* - * Error values passed to errorp - */ -#define PNOERROR 0 -#define PNOMEM 1 -#define PREFCOUNT 2 -#define PUNDEFINED 3 -#define PDOMAIN 4 -#define POVERFLOW 5 - -#define pUndef ((precision) 0) /* An undefined value */ -#define pNull ((precision *) 0) - -#define peq(u, v) (pcmp((u), (v)) == 0) -#define pne(u, v) (pcmp((u), (v)) != 0) -#define pgt(u, v) (pcmp((u), (v)) > 0) -#define plt(u, v) (pcmp((u), (v)) < 0) -#define pge(u, v) (pcmp((u), (v)) >= 0) -#define ple(u, v) (pcmp((u), (v)) <= 0) - -#define peqz(u) (pcmpz(u) == 0) -#define pnez(u) (pcmpz(u) != 0) -#define pltz(u) (pcmpz(u) < 0) -#define pgtz(u) (pcmpz(u) > 0) -#define plez(u) (pcmpz(u) <= 0) -#define pgez(u) (pcmpz(u) >= 0) - -#define peven(u) (!podd(u)) -#define pdiv(u,v) (pdivmod(u,v, (precision *) -1, pNull)) -#define pmod(u,v) (pdivmod(u,v, pNull, (precision *) -1)) -#define pdivr(u,v,r) (pdivmod(u,v, (precision *) -1, r)) -#define pmodq(u,v,q) (pdivmod(u,v, q, (precision *) -1)) - -/* - * Application programs should only use the following definitions; - * - * pnew, pdestroy, pparm, presult and pset - * - * Other variants are internal only! - * All are side-effect safe except for pparm and presult. - * -DDEBUG will enable argument checking for pset and pparm - */ -#ifdef __GNUC__ /* inline is NOT ansii! Sigh. */ -#ifndef BWGC -static inline precision pnew(precision u) { (* (prefc *) u)++; return u; } -static inline void pdestroy(precision u) { - if (u != pUndef && --(*(prefc *) u) == 0) pfree(u); -} -static inline precision pparmq(precision u) { - if (u != pUndef) (* (prefc *) u)++; return u; -} -static inline precision presult(precision u) { - if (u != pUndef) --(*(prefc *) u); return u; -} -static inline precision psetq(precision *up, precision v) { - precision u = *up; - *up = v; - if (v != pUndef) (* (prefc *) v)++; - if (u != pUndef && --(* (prefc *) u) == 0) pfree(u); - return v; -} -#define pvoid(u) pdestroy(u) -#else -extern inline precision pnew(precision u) { return u; } -extern inline void pdestroy(precision u) {} -extern inline precision pparmq(precision u) { return u; } -extern inline precision presult(precision u) { return u; } -extern inline precision psetq(precision *up, precision v) { - precision u = *up; - *up = v; - return v; -} -#define pvoid(u) pdestroy(u) -#endif -#else -#ifndef BWGC -#define pdestroy(u) (void) ((u)!=pUndef&&--(*(prefc *)(u))==0&&pfree(u)) -#define pparmq(u) ((u) != pUndef && (* (prefc *) (u))++, (u)) -#define pvoid(u) pdestroyf(u) -#else -#define pdestroy(u) (void) (0) -#define pparmq(u) (u) -#define pvoid(u) pdestroyf(u) -#endif -#endif - - -#ifdef PDEBUG -#define pset(u, v) psetv(u, v) -#define pparm(u) pparmv(u) -#else -#define pset(u, v) psetq(u, v) -#define pparm(u) pparmq(u) -#endif - -#ifdef __STDC__ /* if ANSI compiler */ -#ifndef __GNUC__ -extern precision pnew(precision); /* initialization */ -extern precision presult(precision); /* function result */ -extern precision psetq(precision *, precision); /* quick assignment */ -#endif -extern precision psetv(precision *, precision); /* checked assignment */ -extern precision pparmv(precision); /* checked parameter */ -extern precision pparmf(precision); /* unchecked parameter (fn) */ - -extern int pcmpz(precision); /* compare to zero */ -extern int pcmp(precision, precision); /* compare */ -extern int picmp(precision, int); /* single digit cmp */ - -extern precision padd(precision, precision); /* add */ -extern precision psub(precision, precision); /* subtract */ -extern precision pmul(precision, precision); /* multiply */ - -extern precision pdivmod(precision, precision, - precision *q, precision *r); - -extern precision pidiv(precision, int); /* single digit pdiv */ -extern int pimod(precision, int); /* single digit pmod */ -extern void pidivmod(precision, int, /* single pdivmod */ - precision *q, int *r); - -extern precision pneg(precision); /* negate */ -extern precision pabs(precision); /* absolute value */ -extern int podd(precision); /* true if odd */ -extern precision phalf(precision); /* divide by two */ - -extern precision pmin(precision, precision); /* minimum value */ -extern precision pmax(precision, precision); /* maximum value */ - -extern precision prand(precision); /* random number generator */ - -extern precision itop(int); /* int to precision */ -extern precision utop(unsigned); /* unsigned to precision */ -extern precision ltop(long); /* long to precision */ -extern precision ultop(unsigned long); /* unsigned long to precision */ - -extern int ptoi(precision); /* precision to int */ -extern unsigned int ptou(precision); /* precision to unsigned */ -extern long ptol(precision); /* precision to long */ -extern unsigned long ptoul(precision); /* precision to unsigned long */ - -extern precision atop(char *); /* ascii to precision */ -extern char *ptoa(precision); /* precision to ascii */ - -extern int btop(precision *result, /* base to precision */ - char *src, unsigned size, int *digitmap, unsigned radix); - -extern int /* precision to base */ - ptob(precision, char *result, unsigned size, char *alphabet, unsigned radix); - -/* - * Can't do prototyping for these unless stdio.h has been included - */ -#ifdef BUFSIZ -extern precision fgetp(FILE *stream); /* input precision */ -extern int fputp(FILE *stream, precision); /* output precision */ -extern int - fprintp(FILE *stream, precision, int minWidth); /* output within a field */ -#else -extern precision fgetp(); /* input precision */ -extern int fputp(); /* output precision */ -extern int fprintp(); /* output within a field */ -#endif - -extern int putp(precision); /* stdout with '\n' */ - -extern void pshow(precision); /* display debug info */ -extern precision prandnum(); /* debug and profil only */ -extern precision pshift(precision, int); /* shift left */ - -extern precision errorp(int errnum, char *routine, char *message); - -extern precision pzero, pone, ptwo; /* constants 0, 1, and 2 */ -extern precision p_one; /* constant -1 */ - -extern precision psqrt(precision); /* square root */ -extern precision pfactorial(precision); /* factorial */ -extern precision pipow(precision, unsigned); /* unsigned int power */ -extern precision ppow(precision, precision); /* precision power */ -extern precision - ppowmod(precision, precision, precision); /* precision power mod m */ -extern int plogb(precision, precision); /* log base b of n */ - -extern precision dtop(double); /* double to precision */ -extern double ptod(precision); /* precision to double */ - -/* - * vector operations - */ -pvector pvundef(pvector, unsigned size); /* local variable entry */ -void pvdestroy(pvector, unsigned size); /* local variable exit */ - -pvector pvalloc(unsigned size); /* pvec allocate */ -void pvfree(pvector, unsigned size); /* pvec free */ - -pvector pvset(pvector, unsigned size, precision value); - -#else - -/* - * Function versions of above if you still want side effects - */ - -#ifndef __GNUC__ -extern precision pnew(); /* initialization */ -extern precision presult(); /* function result */ -extern precision psetq(); /* quick assignment */ -#endif -extern precision psetv(); /* checked assignment */ -extern precision pparmv(); /* checked parameter */ -extern precision pparmf(); /* unchecked parameter (fn) */ - -extern int pcmpz(); /* compare to zero */ -extern int pcmp(); /* compare */ -extern int picmp(); /* single digit compare */ - -extern precision padd(); /* add */ -extern precision psub(); /* subtract */ -extern precision pmul(); /* multiply */ - -extern precision pdivmod(); /* divide/remainder */ -extern void pidivmod(); /* single digit divide/remainder */ -extern precision pidiv(); /* single digit divide */ -extern int pimod(); /* single digit remainder */ -extern precision pneg(); /* negate */ -extern precision pabs(); /* absolute value */ -extern int podd(); /* true if odd */ -extern precision phalf(); /* divide by two */ - -extern precision pmin(); /* minimum value */ -extern precision pmax(); /* maximum value */ - -extern precision prand(); /* random number generator */ - -extern precision itop(); /* int to precision */ -extern precision utop(); /* unsigned to precision */ -extern precision ltop(); /* long to precision */ -extern precision ultop(); /* unsigned long to precision */ - -extern int ptoi(); /* precision to int */ -extern unsigned int ptou(); /* precision to unsigned */ -extern long ptol(); /* precision to long */ -extern unsigned long ptoul(); /* precision to unsigned long */ - -extern precision atop(); /* ascii to precision */ -extern char *ptoa(); /* precision to ascii */ - -extern int btop(); /* base to precision */ -extern int ptob(); /* precision to base */ - -extern precision fgetp(); /* input a precision */ -extern int fputp(); /* output a precision */ -extern int putp(); /* output precision '\n' to stdout */ -extern int fprintp(); /* output a precision within a field */ - -extern void pshow(); /* display debug info */ -extern precision prandnum(); /* for debug and profil only */ -extern precision pshift(); /* shift left */ - -extern precision errorp(); /* user-substitutable error handler */ - -extern precision pzero, pone, ptwo; /* constants 0, 1, and 2 */ -extern precision p_one; /* constant -1 */ - -extern precision psqrt(); /* square root */ -extern precision pfactorial(); /* factorial */ -extern precision pipow(); /* unsigned int power */ -extern precision ppow(); /* precision power */ -extern precision ppowmod(); /* precision power mod m */ -extern int plogb(); /* log base b of n */ - -extern precision dtop(); /* double to precision */ -extern double ptod(); /* precision to double */ - -/* - * vector operations - */ -pvector pvundef(); /* local variable entry */ -void pvdestroy(); /* local variable exit */ -pvector pvalloc(); /* pvec allocate */ -void pvfree(); /* pvec free */ -pvector pvset(); /* set each element to scaler */ - -#endif diff --git a/src/benchmarks/cfrac/primes.c b/src/benchmarks/cfrac/primes.c deleted file mode 100644 index f9dbd84..0000000 --- a/src/benchmarks/cfrac/primes.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * A table of all primes < 65536 - */ -unsigned int primesize = 6542; - -unsigned short primes[] = { - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, - 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, - 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, - 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, - 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, - 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, - 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, - 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, - 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, - 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, - 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, - 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, - 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, - 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, - 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, - 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, - 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, - 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, - 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, - 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, - 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, - 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, - 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, - 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, - 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, - 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, - 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, - 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, - 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, - 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, - 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, - 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, - 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, - 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, - 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, - 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, - 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, - 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, - 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, - 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, - 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, - 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, - 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, - 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, - 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, - 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, - 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, - 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, - 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, - 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, - 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, - 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, - 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, - 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, - 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, - 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, - 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, - 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, - 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, - 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, - 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, - 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, - 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, - 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, - 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, - 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, - 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, - 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, - 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, - 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, - 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, - 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, - 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, - 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, - 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, - 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, - 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, - 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, - 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, - 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, - 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, - 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, - 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, - 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, - 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, - 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, - 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, - 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, - 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, - 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, - 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, - 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, - 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, - 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, - 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, - 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, - 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, - 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, - 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, - 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, - 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, - 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, - 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, - 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, - 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, - 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, - 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, - 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, - 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, - 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, - 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, - 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, - 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, - 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, - 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, - 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, - 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, - 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, - 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, - 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, - 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, - 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, - 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, - 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, - 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, - 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, - 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, - 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, - 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, - 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, - 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, - 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, - 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, - 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, - 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, - 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, - 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, - 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, - 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, - 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, - 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, - 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, - 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, - 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, - 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, - 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, - 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, - 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, - 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, - 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, - 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, - 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, - 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, - 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, - 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, - 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, - 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, - 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, - 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, - 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, - 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, - 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, - 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, - 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, - 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, - 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, - 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, - 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, - 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, - 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, - 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, - 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, - 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, - 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, - 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, - 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, - 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, - 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, - 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, - 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, - 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, - 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, - 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, - 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, - 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, - 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, - 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, - 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, - 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, - 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, - 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, - 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, - 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, - 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, - 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, - 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, - 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, - 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, - 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, - 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, - 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, - 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, - 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, - 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, - 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, - 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, - 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, - 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, - 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, - 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, - 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, - 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, - 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, - 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, - 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, - 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, - 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, - 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, - 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, - 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, - 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, - 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, - 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, - 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, - 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, - 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, - 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, - 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, - 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, - 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, - 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, - 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, - 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, - 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, - 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, - 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, - 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, - 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, - 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, - 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, - 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, - 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, - 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, - 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, - 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, - 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, - 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, - 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, - 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, - 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, - 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, - 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, - 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, - 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, - 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, - 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, - 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, - 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, - 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, - 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, - 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, - 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, - 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, - 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, - 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, - 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, - 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, - 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, - 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, - 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, - 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, - 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, - 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, - 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, - 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, - 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, - 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, - 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, - 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, - 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, - 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, - 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, - 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, - 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, - 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, - 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, - 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, - 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, - 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, - 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, - 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, - 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, - 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, - 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, - 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, - 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, - 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, - 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, - 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, - 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, - 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, - 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, - 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, - 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, - 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, - 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, - 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, - 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, - 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, - 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, - 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, - 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, - 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, - 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, - 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, - 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, - 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, - 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, - 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, - 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, - 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, - 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, - 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, - 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, - 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, - 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, - 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, - 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, - 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, - 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, - 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, - 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, - 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, - 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, - 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, - 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, - 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, - 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, - 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, - 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, - 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, - 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, - 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, - 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, - 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, - 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, - 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, - 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, - 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, - 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, - 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, - 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, - 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, - 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, - 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, - 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, - 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, - 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, - 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, - 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, - 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, - 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, - 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, - 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, - 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, - 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, - 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, - 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, - 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, - 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, - 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, - 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, - 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, - 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, - 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, - 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, - 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, - 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, - 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, - 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, - 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, - 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, - 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, - 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, - 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, - 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, - 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, - 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, - 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, - 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, - 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, - 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, - 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, - 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, - 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, - 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, - 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, - 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, - 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, - 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, - 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, - 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, - 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, - 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, - 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, - 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, - 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, - 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, - 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, - 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, - 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, - 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, - 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, - 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, - 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, - 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, - 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, - 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, - 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, - 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, - 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, - 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, - 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, - 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, - 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, - 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, - 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, - 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, - 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, - 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, - 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, - 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, - 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, - 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, - 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, - 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, - 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, - 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, - 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, - 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, - 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, - 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, - 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, - 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, - 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, - 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, - 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, - 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, - 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, - 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, - 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, - 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, - 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, - 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, - 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, - 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, - 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, - 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, - 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, - 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, - 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, - 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, - 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, - 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, - 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, - 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, - 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, - 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, - 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, - 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, - 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, - 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, - 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, - 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, - 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, - 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, - 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, - 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, - 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, - 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, - 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, - 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, - 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, - 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, - 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, - 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, - 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, - 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, - 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, - 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, - 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, - 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, - 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, - 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, - 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, - 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, - 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, - 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, - 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, - 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, - 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, - 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, - 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, - 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, - 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, - 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, - 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, - 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, - 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, - 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, - 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, - 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, - 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, - 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, - 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, - 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, - 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, - 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, - 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, - 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, - 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, - 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, - 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, - 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, - 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, - 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, - 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, - 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, - 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, - 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, - 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, - 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, - 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, - 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, - 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, - 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, - 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, - 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, - 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, - 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, - 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, - 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, - 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, - 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, - 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, - 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, - 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, - 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, - 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, - 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, - 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, - 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, - 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, - 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, - 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, - 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, - 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, - 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, - 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, - 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, - 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, - 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, - 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, - 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, - 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, - 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, - 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, - 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, - 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, - 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, - 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, - 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, - 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, - 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, - 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, - 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, - 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, - 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, - 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, - 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, - 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, - 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, - 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, - 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, - 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, - 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, - 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, - 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, - 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, - 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, - 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, - 65519, 65521, 1 -}; diff --git a/src/benchmarks/cfrac/primes.h b/src/benchmarks/cfrac/primes.h deleted file mode 100644 index 206f480..0000000 --- a/src/benchmarks/cfrac/primes.h +++ /dev/null @@ -1,2 +0,0 @@ -extern unsigned int primesize; -extern unsigned short primes[]; diff --git a/src/benchmarks/cfrac/psqrt.c b/src/benchmarks/cfrac/psqrt.c deleted file mode 100644 index 00531a6..0000000 --- a/src/benchmarks/cfrac/psqrt.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "precision.h" - -/* - * Square root - */ -precision psqrt(y) - precision y; -{ - int i; - precision x = pUndef, lastx = pUndef; - - i = pcmpz(pparm(y)); - if (i == 0) { /* if y == 0 */ - pset(&lastx, pzero); - } else if (i < 0) { /* if y negative */ - pset(&x, errorp(PDOMAIN, "psqrt", "negative argument")); - } else { - pset(&x, y); - do { - pset(&lastx, x); - pset(&x, phalf(padd(x, pdiv(y, x)))); - } while (plt(x, lastx)); - } - - pdestroy(x); - - pdestroy(y); - return presult(lastx); -} diff --git a/src/benchmarks/cfrac/psub.c b/src/benchmarks/cfrac/psub.c deleted file mode 100644 index d887287..0000000 --- a/src/benchmarks/cfrac/psub.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "pdefs.h" -#include "precision.h" -#include <string.h> - -#ifdef ASM_16BIT -#include "asm16bit.h" -#endif - -/* - * Subtract u from v (assumes normalized) - */ -precision psub(u, v) -#ifndef ASM_16BIT - precision u, v; -{ - register digitPtr HiDigit, wPtr, uPtr; - register digitPtr vPtr; -#else - register precision u, v; -{ - register digitPtr wPtr, uPtr; -#endif - precision w; - register accumulator temp; -#ifndef ASM_16BIT - register digit noborrow; -#endif - register int i; - - (void) pparm(u); - (void) pparm(v); - if (u->sign != v->sign) { /* Are we actually adding? */ - w = pUndef; - v->sign = !v->sign; /* may generate -0 */ - pset(&w, padd(u, v)); - v->sign = !v->sign; - } else { - i = pcmp(u, v); - if (u->sign) i = -i; /* compare magnitudes only */ - - if (i < 0) { - w = u; u = v; v = w; /* make u the largest */ - } - - w = palloc(u->size); /* may produce much wasted storage */ - if (w == pUndef) return w; - - if (i < 0) w->sign = !u->sign; else w->sign = u->sign; - - uPtr = u->value; - wPtr = w->value; -#ifndef ASM_16BIT - vPtr = v->value; - noborrow = 1; - - HiDigit = v->value + v->size; /* digits in both args */ - do { - temp = (BASE-1) - *vPtr++; /* 0 <= temp < base */ - temp += *uPtr++; /* 0 <= temp < 2*base-1 */ - temp += noborrow; /* 0 <= temp < 2*base */ - noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ - *wPtr++ = modBase(temp); - } while (vPtr < HiDigit); - - HiDigit = u->value + u->size; /* propagate borrow */ - while (uPtr < HiDigit) { - temp = (BASE-1) + *uPtr++; - temp += noborrow; /* 0 <= temp < 2 * base */ - noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ - *wPtr++ = modBase(temp); - } /* noborrow = 1 */ -#else - i = v->size; - temp = u->size - i; - if (temp > 0) { - memcpy(wPtr + i, uPtr + i, temp * sizeof(digit)); - } - if (memsubw(wPtr, uPtr, v->value, i)) { /* trashes uPtr */ - memdecw(wPtr + i, temp); - } - wPtr += w->size; -#endif - do { /* normalize */ - if (*--wPtr != 0) break; - } while (wPtr > w->value); - w->size = (wPtr - w->value) + 1; - } - - pdestroy(u); - pdestroy(v); - return presult(w); -} diff --git a/src/benchmarks/cfrac/ptoa.c b/src/benchmarks/cfrac/ptoa.c deleted file mode 100644 index a928ea2..0000000 --- a/src/benchmarks/cfrac/ptoa.c +++ /dev/null @@ -1,71 +0,0 @@ -#include <string.h> -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Return the character string decimal value of a Precision - */ -#if (BASE > 10) -#define CONDIGIT(d) ((d) < 10 ? (d) + '0' : (d) + 'a'-10) -#else -#define CONDIGIT(d) ((d) + '0') -#endif - -char *ptoa(u) - precision u; -{ - register accumulator temp; - register char *dPtr; - char *d; - int i = 0; - unsigned int consize; - precision r, v, pbase; - register int j; - - (void) pparm(u); - r = pUndef; - v = pUndef; - pbase = pUndef; - - consize = (unsigned int) u->size; - if (consize > MAXINT / aDigits) { - consize = (consize / pDigits) * aDigits; - } else { - consize = (consize * aDigits) / pDigits; - } - - consize += aDigitLog + 2; /* leading 0's, sign, & '\0' */ - d = (char *) allocate((unsigned int) consize); - if (d == (char *) 0) return d; - - pset(&v, pabs(u)); - pset(&pbase, utop(aDigit)); - - dPtr = d + consize; - *--dPtr = '\0'; /* null terminate string */ - i = u->sign; /* save sign */ - do { - pdivmod(v, pbase, &v, &r); - temp = ptou(r); /* Assumes unsigned and accumulator same! */ - j = aDigitLog; - do { - *--dPtr = CONDIGIT(temp % aBase); /* remainder */ - temp = temp / aBase; - } while (--j > 0); - } while (pnez(v)); - - while (*dPtr == '0') dPtr++; /* toss leading zero's */ - if (*dPtr == '\0') --dPtr; /* but don't waste zero! */ - if (i) *--dPtr = '-'; - if (dPtr > d) { /* ASSUME copied from lower to higher! */ - (void) memcpy(d, dPtr, consize - (dPtr - d)); - } - - pdestroy(pbase); - pdestroy(v); - pdestroy(r); - - pdestroy(u); - return d; -} diff --git a/src/benchmarks/cfrac/ptob.c b/src/benchmarks/cfrac/ptob.c deleted file mode 100644 index d5b04c1..0000000 --- a/src/benchmarks/cfrac/ptob.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "pdefs.h" -#include "precision.h" - -/* - * Convert a precision to a given base (the sign is ignored) - * - * Input: - * u - the number to convert - * dest - Where to put the ASCII representation radix - * WARNING! Not '\0' terminated, this is an exact image - * size - the number of digits of dest. - * (alphabet[0] padded on left) - * if size is too small, truncation occurs on left - * alphabet - A mapping from each radix digit to it's character digit - * (note: '\0' is perfectly OK as a digit) - * radix - The size of the alphabet, and the conversion radix - * 2 <= radix < 256. - * - * Returns: - * -1 if invalid radix - * 0 if successful - * >0 the number didn't fit - */ -int ptob(u, dest, size, alphabet, radix) - precision u; /* the number to convert */ - char *dest; /* where to place the converted ascii */ - unsigned int size; /* the size of the result in characters */ - char *alphabet; /* the character set forming the radix */ - register unsigned int radix; /* the size of the character set */ -{ - register accumulator temp; - register unsigned int i; - register char *chp; - unsigned int lgclump; - int res = 0; - - precision r = pUndef, v = pUndef, pbase = pUndef; - - if (radix > 256 || radix < 2) return -1; - if (size == 0) return 1; - - (void) pparm(u); - temp = radix; - i = 1; - while (temp * radix > temp) { - temp *= radix; - i++; - } - lgclump = i; - - pset(&v, pabs(u)); - pset(&pbase, utop(temp)); /* assumes accumulator and int are the same! */ - - chp = dest + size; - do { - pdivmod(v, pbase, &v, &r); - temp = ptou(r); /* assumes accumulator and int are the same! */ - i = lgclump; - do { - *--chp = alphabet[temp % radix]; /* remainder */ - temp = temp / radix; - if (chp == dest) goto bail; - } while (--i > 0); - } while pnez(v); - - if (chp > dest) do { - *--chp = *alphabet; - } while (chp > dest); - -bail: - if (pnez(v) || temp != 0) { /* check for overflow */ - res = 1; - } - - pdestroy(pbase); - pdestroy(v); - pdestroy(r); - - pdestroy(u); - return res; -} diff --git a/src/benchmarks/cfrac/ptou.c b/src/benchmarks/cfrac/ptou.c deleted file mode 100644 index b8ca07b..0000000 --- a/src/benchmarks/cfrac/ptou.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Precision to unsigned - */ -unsigned int ptou(u) - precision u; -{ - register digitPtr uPtr; - register accumulator temp; - - (void) pparm(u); - if (u->sign) { - temp = (unsigned long) errorp(PDOMAIN, "ptou", "negative argument"); - } else { - uPtr = u->value + u->size; - temp = 0; - do { - if (temp > divBase(MAXUNSIGNED - *--uPtr)) { - temp = (unsigned long) errorp(POVERFLOW, "ptou", "overflow"); - break; - } - temp = mulBase(temp); - temp += *uPtr; - } while (uPtr > u->value); - } - pdestroy(u); - return (unsigned int) temp; -} diff --git a/src/benchmarks/cfrac/seive.h b/src/benchmarks/cfrac/seive.h deleted file mode 100644 index 2e1cb85..0000000 --- a/src/benchmarks/cfrac/seive.h +++ /dev/null @@ -1,3 +0,0 @@ -extern unsigned long seivesize; - -extern unsigned char seive[]; diff --git a/src/benchmarks/cfrac/utop.c b/src/benchmarks/cfrac/utop.c deleted file mode 100644 index 4d87c04..0000000 --- a/src/benchmarks/cfrac/utop.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "pdefs.h" -#include "pcvt.h" -#include "precision.h" - -/* - * Unsigned to Precision - */ -precision utop(i) - register unsigned int i; -{ - register digitPtr uPtr; - register precision u = palloc(INTSIZE); - - if (u == pUndef) return pUndef; - - u->sign = false; - uPtr = u->value; - do { - *uPtr++ = modBase(i); - i = divBase(i); - } while (i != 0); - - u->size = (uPtr - u->value); - return presult(u); -} diff --git a/src/benchmarks/dj_trace.py b/src/benchmarks/dj_trace.py deleted file mode 100644 index 22398e6..0000000 --- a/src/benchmarks/dj_trace.py +++ /dev/null @@ -1,445 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Benchmark definition using the traces collected by DJ Delorie""" - -import os -import subprocess -import sys -import re -from urllib.request import urlretrieve -import matplotlib.pyplot as plt -import numpy as np - -from src.artifact import ArchiveArtifact -from src.benchmark import Benchmark -from src.globalvars import summary_file_ext -import src.plots as abplt -from src.util import print_status - -COMMA_SEP_NUMBER_RE = "(?:\\d*(?:,\\d*)?)*" -RSS_RE = f"(?P<rss>{COMMA_SEP_NUMBER_RE})" -TIME_RE = f"(?P<time>{COMMA_SEP_NUMBER_RE})" - -CYCLES_RE = re.compile(f"^{TIME_RE} cycles$") -CPU_TIME_RE = re.compile(f"^{TIME_RE} usec across.*threads$") - -MAX_RSS_RE = re.compile(f"^{RSS_RE} Kb Max RSS") -IDEAL_RSS_RE = re.compile(f"^{RSS_RE} Kb Max Ideal RSS") - -MALLOC_RE = re.compile(f"^Avg malloc time:\\s*{TIME_RE} in.*calls$") -CALLOC_RE = re.compile(f"^Avg calloc time:\\s*{TIME_RE} in.*calls$") -REALLOC_RE = re.compile(f"^Avg realloc time:\\s*{TIME_RE} in.*calls$") -FREE_RE = re.compile(f"^Avg free time:\\s*{TIME_RE} in.*calls$") - - -class BenchmarkDJTrace(Benchmark): - """DJ Trace Benchmark - - This benchmark uses the workload simulator written by DJ Delorie to - simulate workloads provided by him under https://delorie.com/malloc. Those - workloads are generated from traces of real aplications and are also used - by delorie to measure improvements in the glibc allocator. - """ - def __init__(self): - name = "dj_trace" - - self.cmd = "trace_run{binary_suffix} {workload_dir}/dj_workloads/{workload}.wl" - self.measure_cmd = "" - - self.args = { - "workload": [ - "389-ds-2", "dj", "dj2", "mt_test_one_alloc", "oocalc", - "qemu-virtio", "qemu-win7", "proprietary-1", "proprietary-2" - ] - } - - self.results = { - "389-ds-2": { - "malloc": 170500018, - "calloc": 161787184, - "realloc": 404134, - "free": 314856324, - "threads": 41 - }, - "dj": { - "malloc": 2000000, - "calloc": 200, - "realloc": 0, - "free": 2003140, - "threads": 201 - }, - "dj2": { - "malloc": 29263321, - "calloc": 3798404, - "realloc": 122956, - "free": 32709054, - "threads": 36 - }, - "mt_test_one_alloc": { - "malloc": 524290, - "calloc": 1, - "realloc": 0, - "free": 594788, - "threads": 2 - }, - "oocalc": { - "malloc": 6731734, - "calloc": 38421, - "realloc": 14108, - "free": 6826686, - "threads": 88 - }, - "qemu-virtio": { - "malloc": 1772163, - "calloc": 146634, - "realloc": 59813, - "free": 1954732, - "threads": 3 - }, - "qemu-win7": { - "malloc": 980904, - "calloc": 225420, - "realloc": 89880, - "free": 1347825, - "threads": 6 - }, - "proprietary-1": { - "malloc": 316032131, - "calloc": 5642, - "realloc": 84, - "free": 319919727, - "threads": 20 - }, - "proprietary-2": { - "malloc": 9753948, - "calloc": 4693, - "realloc": 117, - "free": 10099261, - "threads": 19 - } - } - - self.requirements = ["trace_run"] - super().__init__(name) - - def prepare(self): - super().prepare() - - workloads = ArchiveArtifact( - "dj_workloads", - "https://www4.cs.fau.de/~flow/allocbench/dj_workloads.tar.xz", - "tar", "c9bc499eeba8023bca28a755fffbaf9200a335ad") - - self.workload_dir = workloads.provide() - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - def to_int(string): - return int(string.replace(',', "")) - - regexs = {7: MALLOC_RE, 8: CALLOC_RE, 9: REALLOC_RE, 10: FREE_RE} - functions = {7: "malloc", 8: "calloc", 9: "realloc", 10: "free"} - for i, line in enumerate(stdout.splitlines()): - if i == 0: - result["cycles"] = to_int(CYCLES_RE.match(line).group("time")) - elif i == 2: - result["cputime"] = to_int( - CPU_TIME_RE.match(line).group("time")) - elif i == 3: - result["Max_RSS"] = to_int(MAX_RSS_RE.match(line).group("rss")) - elif i == 4: - result["Ideal_RSS"] = to_int( - IDEAL_RSS_RE.match(line).group("rss")) - elif i in [7, 8, 9, 10]: - res = regexs[i].match(line) - fname = functions[i] - result["avg_" + fname] = to_int(res.group("time")) - - def summary(self): - args = self.results["args"] - allocators = self.results["allocators"] - - abplt.plot(self, - "{cputime}/1000", - plot_type='bar', - fig_options={ - 'ylabel': "time in ms", - 'title': "total runtime", - }, - file_postfix="runtime") - - # Function Times - func_times_means = {allocator: {} for allocator in allocators} - xa = np.arange(0, 6, 1.5) - for perm in self.iterate_args(args=args): - for i, allocator in enumerate(allocators): - x_vals = [x + i / len(allocators) for x in xa] - - func_times_means[allocator][perm] = [0, 0, 0, 0] - - func_times_means[allocator][perm][0] = np.mean( - [x["avg_malloc"] for x in self.results[allocator][perm]]) - func_times_means[allocator][perm][1] = np.mean( - [x["avg_calloc"] for x in self.results[allocator][perm]]) - func_times_means[allocator][perm][2] = np.mean( - [x["avg_realloc"] for x in self.results[allocator][perm]]) - func_times_means[allocator][perm][3] = np.mean( - [x["avg_free"] for x in self.results[allocator][perm]]) - - plt.bar(x_vals, - func_times_means[allocator][perm], - width=0.25, - align="center", - label=allocator, - color=allocators[allocator]["color"]) - - plt.legend(loc="best") - plt.xticks(xa + 1 / len(allocators) * 2, [ - "malloc\n" + str(self.results[perm.workload]["malloc"]) + - "\ncalls", "calloc\n" + - str(self.results[perm.workload]["calloc"]) + "\ncalls", - "realloc\n" + str(self.results[perm.workload]["realloc"]) + - "\ncalls", - "free\n" + str(self.results[perm.workload]["free"]) + "\ncalls" - ]) - plt.ylabel("cycles") - plt.title(f"Avg. runtime of API functions {perm.workload}") - plt.savefig(".".join( - [self.name, perm.workload, "apitimes", summary_file_ext])) - plt.clf() - - # Memusage - # hack ideal rss in data set - allocators["Ideal_RSS"] = {"color": "xkcd:gold"} - self.results["stats"]["Ideal_RSS"] = {} - for perm in self.iterate_args(args=args): - ideal_rss = self.results[list( - allocators.keys())[0]][perm][0]["Ideal_RSS"] / 1000 - self.results["stats"]["Ideal_RSS"][perm] = { - "mean": { - "Max_RSS": ideal_rss - }, - "std": { - "Max_RSS": 0 - } - } - - abplt.plot(self, - "{Max_RSS}/1000", - plot_type='bar', - fig_options={ - 'ylabel': "Max RSS in MB", - 'title': "Max RSS (VmHWM)", - }, - file_postfix="newrss") - - # self.barplot_fixed_arg("{Max_RSS}/1000", - # ylabel='"Max RSS in MB"', - # title='"Highwatermark of Vm (VmHWM)"', - # file_postfix="newrss") - - del allocators["Ideal_RSS"] - del self.results["stats"]["Ideal_RSS"] - - rss_means = {allocator: {} for allocator in allocators} - for perm in self.iterate_args(args=args): - for i, allocator in enumerate(allocators): - d = [x["Max_RSS"] for x in self.results[allocator][perm]] - # data is in kB - rss_means[allocator][perm] = np.mean(d) / 1000 - - plt.bar([i], - rss_means[allocator][perm], - label=allocator, - color=allocators[allocator]["color"]) - - # add ideal rss - y_val = self.results[list( - allocators.keys())[0]][perm][0]["Ideal_RSS"] / 1000 - plt.bar([len(allocators)], y_val, label="Ideal RSS") - - plt.legend(loc="best") - plt.ylabel("Max RSS in MB") - plt.title(f"Maximal RSS (VmHWM) {perm.workload}") - plt.savefig(".".join( - [self.name, perm.workload, "rss", summary_file_ext])) - plt.clf() - - abplt.export_stats_to_csv(self, "Max_RSS") - abplt.export_stats_to_csv(self, "cputime") - - abplt.export_stats_to_dataref(self, "Max_RSS") - abplt.export_stats_to_dataref(self, "cputime") - - # Big table - abplt.write_tex_table(self, [{ - "label": "Runtime [ms]", - "expression": "{cputime}/1000", - "sort": "<" - }, { - "label": "Max RSS [MB]", - "expression": "{Max_RSS}/1000", - "sort": "<" - }], - file_postfix="table") - - # Tables - for perm in self.iterate_args(args=args): - # collect data - d = {allocator: {} for allocator in allocators} - for i, allocator in enumerate(allocators): - d[allocator]["time"] = [ - x["cputime"] for x in self.results[allocator][perm] - ] - d[allocator]["rss"] = [ - x["Max_RSS"] for x in self.results[allocator][perm] - ] - - times = { - allocator: np.mean(d[allocator]["time"]) - for allocator in allocators - } - tmin = min(times.values()) - tmax = max(times.values()) - - rss = { - allocator: np.mean(d[allocator]["rss"]) - for allocator in allocators - } - rssmin = min(rss.values()) - rssmax = max(rss.values()) - - fname = ".".join([self.name, perm.workload, "table.tex"]) - with open(fname, "w") as f: - print("\\documentclass{standalone}", file=f) - print("\\usepackage{xcolor}", file=f) - print("\\begin{document}", file=f) - print("\\begin{tabular}{| l | l | l |}", file=f) - print( - "& Zeit (ms) / $\\sigma$ (\\%) & VmHWM (KB) / $\\sigma$ (\\%) \\\\", - file=f) - print("\\hline", file=f) - - for allocator in allocators: - print(allocator.replace("_", "\\_"), end=" & ", file=f) - - s = "\\textcolor{{{}}}{{{:.2f}}} / {:.4f}" - - t = d[allocator]["time"] - m = times[allocator] - if m == tmin: - color = "green" - elif m == tmax: - color = "red" - else: - color = "black" - print(s.format(color, m, np.std(t) / m), end=" & ", file=f) - - t = d[allocator]["rss"] - m = rss[allocator] - if m == rssmin: - color = "green" - elif m == rssmax: - color = "red" - else: - color = "black" - print(s.format(color, m, - np.std(t) / m if m else 0), - "\\\\", - file=f) - - print("\\end{tabular}", file=f) - print("\\end{document}", file=f) - - # Create summary similar to DJ's at - # https://sourceware.org/ml/libc-alpha/2017-01/msg00452.html - with open(self.name + "_plain.txt", "w") as f: - # Absolutes - fmt = "{:<20} {:>15} {:>7} {:>7} {:>7} {:>7} {:>7}" - for i, allocator in enumerate(allocators): - print("{0} {1} {0}".format("-" * 10, allocator), file=f) - print(fmt.format("Workload", "Total", "malloc", "calloc", - "realloc", "free", "RSS"), - file=f) - - for perm in self.iterate_args(args=args): - cycles = abplt._get_y_data(self, "{cycles}", allocator, perm)[0] - times = [t for t in func_times_means[allocator][perm]] - rss = rss_means[allocator][perm] - print(fmt.format(perm.workload, cycles, times[0], times[1], - times[2], times[3], rss), - file=f) - - print(file=f) - - # Changes. First allocator in allocators is the reference - fmt_changes = "{:<20} {:>14.0f}% {:>6.0f}% {:>6.0f}% {:>6.0f}% {:>6.0f}% {:>6.0f}%" - for allocator in list(allocators)[1:]: - print("{0} Changes {1} {0}".format("-" * 10, allocator), - file=f) - print(fmt.format("Workload", "Total", "malloc", "calloc", - "realloc", "free", "RSS"), - file=f) - - ref_alloc = list(allocators)[0] - cycles_change_means = [] - times_change_means = [] - rss_change_means = [] - for perm in self.iterate_args(args=args): - - normal_cycles = cycles_means[ref_alloc][perm] - if normal_cycles: - cycles = np.round(cycles_means[allocator][perm] / - normal_cycles * 100) - else: - cycles = 0 - cycles_change_means.append(cycles) - - normal_times = func_times_means[ref_alloc][perm] - times = [0, 0, 0, 0] - for i in range(0, len(times)): - t = func_times_means[allocator][perm][i] - nt = normal_times[i] - if nt != 0: - times[i] = np.round(t / nt * 100) - times_change_means.append(times) - - normal_rss = rss_means[ref_alloc][perm] - if normal_rss: - rss = np.round(rss_means[allocator][perm] / - normal_rss * 100) - else: - rss = 0 - rss_change_means.append(rss) - - print(fmt_changes.format(perm.workload, cycles, times[0], - times[1], times[2], times[3], - rss), - file=f) - print(file=f) - tmeans = [0, 0, 0, 0] - for i in range(0, len(times)): - tmeans[i] = np.mean( - [times[i] for times in times_change_means]) - print(fmt_changes.format("Mean:", np.mean(cycles_change_means), - tmeans[0], tmeans[1], tmeans[2], - tmeans[3], np.mean(rss_change_means)), - '\n', - file=f) - - -dj_trace = BenchmarkDJTrace() diff --git a/src/benchmarks/dj_trace/Makefile b/src/benchmarks/dj_trace/Makefile deleted file mode 100644 index 0b04678..0000000 --- a/src/benchmarks/dj_trace/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -OPTFLAGS ?= -O3 -DNDEBUG - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -.PHONY = all clean - -all: $(OBJDIR)/trace_run - -$(OBJDIR)/trace_run: trace_run.c | $(OBJDIR) - @echo compiling $@... - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/dj_trace/trace_run.c b/src/benchmarks/dj_trace/trace_run.c deleted file mode 100644 index 604d01e..0000000 --- a/src/benchmarks/dj_trace/trace_run.c +++ /dev/null @@ -1,750 +0,0 @@ -#define _LARGEFILE64_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <pthread.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/resource.h> -#include <fcntl.h> -#include <unistd.h> - -// #include "malloc.h" -#include <malloc.h> - -// #include "mtrace.h" -/* Codes for the simulator/workload programs. Copied from mtrace.h. */ -#define C_NOP 0 -#define C_DONE 1 -#define C_MALLOC 2 -#define C_CALLOC 3 -#define C_REALLOC 4 -#define C_FREE 5 -#define C_SYNC_W 6 -#define C_SYNC_R 7 -#define C_ALLOC_PTRS 8 -#define C_ALLOC_SYNCS 9 -#define C_NTHREADS 10 -#define C_START_THREAD 11 -#define C_MEMALIGN 12 -#define C_VALLOC 13 -#define C_PVALLOC 14 -#define C_POSIX_MEMALIGN 15 - -#if UINTPTR_MAX == 0xffffffffffffffff - -#define ticks_t int64_t -/* Setting quick_run to 1 allows the simulator to model - only the allocation and deallocation accounting via - atomic_rss. The actual allocations are skipped. This - mode is useful to verify the workload file. */ -#define quick_run 0 - -static __inline__ ticks_t rdtsc_s(void) -{ - unsigned a, d; - asm volatile("cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx"); - asm volatile("rdtscp" : "=a" (a), "=d" (d)); - return ((unsigned long long)a) | (((unsigned long long)d) << 32); -} - -static __inline__ ticks_t rdtsc_e(void) -{ - unsigned a, d; - asm volatile("rdtscp" : "=a" (a), "=d" (d)); - asm volatile("cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx"); - return ((unsigned long long)a) | (((unsigned long long)d) << 32); -} - -#else - -#define ticks_t int32_t - -static __inline__ ticks_t rdtsc_s(void) -{ - unsigned a, d; - asm volatile("cpuid" ::: "%ax", "%bx", "%cx", "%dx"); - asm volatile("rdtsc" : "=a" (a), "=d" (d)); - return ((unsigned long)a) | (((unsigned long)d) << 16); -} - -static __inline__ ticks_t rdtsc_e(void) -{ - unsigned a, d; - asm volatile("rdtscp" : "=a" (a), "=d" (d)); - asm volatile("cpuid" ::: "%ax", "%bx", "%cx", "%dx"); - return ((unsigned long)a) | (((unsigned long)d) << 16); -} - -#endif - -static ticks_t diff_timeval (struct timeval e, struct timeval s) -{ - ticks_t usec; - if (e.tv_usec < s.tv_usec) - usec = (e.tv_usec + 1000000 - s.tv_usec) + (e.tv_sec-1 - s.tv_sec)*1000000; - else - usec = (e.tv_usec - s.tv_usec) + (e.tv_sec - s.tv_sec)*1000000; - return usec; -} - -#if 1 -#define Q1 -#define Q2 -#else -pthread_mutex_t genmutex = PTHREAD_MUTEX_INITIALIZER; -#define Q1 pthread_mutex_lock(&genmutex) -#define Q2 pthread_mutex_unlock(&genmutex) -#endif - -pthread_mutex_t cmutex = PTHREAD_MUTEX_INITIALIZER; -#define NCBUF 10 -static char cbuf[NCBUF][30]; -static int ci = 0; - -char *comma(ticks_t x) -{ - char buf[30], *bs, *bd; - int l, i, idx; - - pthread_mutex_lock(&cmutex); - ci = (ci + 1) % NCBUF; - idx = ci; - pthread_mutex_unlock(&cmutex); - bs = buf; - bd = cbuf[idx]; - - sprintf(buf, "%lld", (long long int)x); - l = strlen(buf); - i = l; - while (*bs) - { - *bd++ = *bs++; - i--; - if (i % 3 == 0 && *bs) - *bd++ = ','; - } - *bd = 0; - return cbuf[idx]; -} - -static volatile void **ptrs; -static volatile size_t *sizes; -static size_t n_ptrs; -static volatile char *syncs; -static pthread_mutex_t *mutexes; -static pthread_cond_t *conds; -static size_t n_syncs; - -static pthread_mutex_t stat_mutex = PTHREAD_MUTEX_INITIALIZER; -ticks_t malloc_time = 0, malloc_count = 0; -ticks_t calloc_time = 0, calloc_count = 0; -ticks_t realloc_time = 0, realloc_count = 0; -ticks_t free_time = 0, free_count = 0; - -size_t ideal_rss = 0; -size_t max_ideal_rss = 0; -static pthread_mutex_t rss_mutex = PTHREAD_MUTEX_INITIALIZER; - -void atomic_rss (ssize_t delta) -{ - pthread_mutex_lock (&rss_mutex); - ideal_rss += delta; - if (max_ideal_rss < ideal_rss) - max_ideal_rss = ideal_rss; - pthread_mutex_unlock (&rss_mutex); -} - -pthread_mutex_t stop_mutex = PTHREAD_MUTEX_INITIALIZER; -int threads_done = 0; - -//#define dprintf printf -#define dprintf(...) (void)1 - -//#define mprintf printf -//#define MDEBUG 1 -#define mprintf(...) (void)1 - -#define myabort() my_abort_2(thrc, __LINE__) -void -my_abort_2 (pthread_t thrc, int line) -{ - fprintf(stderr, "Abort thread %p at line %d\n", (void *)thrc, line); - abort(); -} - -/*------------------------------------------------------------*/ -/* Wrapper around I/O routines */ - -int io_fd; - -#define IOSIZE 65536 -#define IOMIN 4096 - -static pthread_mutex_t io_mutex = PTHREAD_MUTEX_INITIALIZER; - -typedef struct { - unsigned char buf[IOSIZE]; - size_t incr; - size_t max_incr; - size_t buf_base; - size_t buf_idx; - int saw_eof; -} IOPerThreadType; - -IOPerThreadType main_io; -IOPerThreadType *thread_io; - -void -io_init (IOPerThreadType *io, size_t file_offset, int incr) -{ - if (incr > IOSIZE) - incr = IOSIZE; - if (incr < IOMIN) - incr = IOMIN; - - io->buf_base = file_offset; - io->buf_idx = 0; - io->incr = incr; - - pthread_mutex_lock (&io_mutex); - lseek64 (io_fd, io->buf_base, SEEK_SET); - // short read OK, the eof is just to prevent runaways from bad data. - if (read (io_fd, io->buf, incr) < 0) - io->saw_eof = 1; - else - io->saw_eof = 0; - pthread_mutex_unlock (&io_mutex); -} - -unsigned char -io_read (IOPerThreadType *io) -{ - if (io->buf_idx >= io->incr) - io_init (io, io->buf_base + io->buf_idx, io->incr); - if (io->saw_eof) - return 0xff; - return io->buf [io->buf_idx++]; -} - -unsigned char -io_peek (IOPerThreadType *io) -{ - if (io->buf_idx >= io->incr) - io_init (io, io->buf_base + io->buf_idx, io->incr); - if (io->saw_eof) - return 0xff; - return io->buf [io->buf_idx]; -} - -size_t -io_pos (IOPerThreadType *io) -{ - return io->buf_base + io->buf_idx; -} - -/*------------------------------------------------------------*/ - -static void -wmem (volatile void *ptr, int count) -{ - char *p = (char *)ptr; - int i; - - if (!p) - return; - - for (i=0; i<count; i++) - p[i] = 0x11; -} -#define xwmem(a,b) - -static size_t get_int (IOPerThreadType *io) -{ - size_t rv = 0; - while (1) - { - unsigned char c = io_read (io); - rv |= (c & 0x7f); - if (c & 0x80) - rv <<= 7; - else - return rv; - } -} - -static void free_wipe (size_t idx) -{ - char *cp = (char *)ptrs[idx]; - if (cp == NULL) - return; - size_t sz = sizes[idx]; - size_t i; - for (i=0; i<sz; i++) - { - if (i % 8 == 1) - cp[i] = i / 8; - else - cp[i] = 0x22; - } -} - -static void * -thread_common (void *my_data_v) -{ - pthread_t thrc = pthread_self (); - size_t p1, p2, sz, sz2; - IOPerThreadType *io = (IOPerThreadType *)my_data_v; - ticks_t my_malloc_time = 0, my_malloc_count = 0; - ticks_t my_calloc_time = 0, my_calloc_count = 0; - ticks_t my_realloc_time = 0, my_realloc_count = 0; - ticks_t my_free_time = 0, my_free_count = 0; - ticks_t stime, etime; - int thread_idx = io - thread_io; -#ifdef MDEBUG - volatile void *tmp; -#endif - - while (1) - { - unsigned char this_op = io_peek (io); - if (io->saw_eof) - myabort(); - dprintf("op %p:%ld is %d\n", (void *)thrc, io_pos (io), io_peek (io)); - switch (io_read (io)) - { - case C_NOP: - break; - - case C_DONE: - dprintf("op %p:%ld DONE\n", (void *)thrc, io_pos (io)); - pthread_mutex_lock (&stat_mutex); - malloc_time += my_malloc_time; - calloc_time += my_calloc_time; - realloc_time += my_realloc_time; - free_time += my_free_time; - malloc_count += my_malloc_count; - calloc_count += my_calloc_count; - realloc_count += my_realloc_count; - free_count += my_free_count; - threads_done ++; - pthread_mutex_unlock (&stat_mutex); - pthread_mutex_lock(&stop_mutex); - pthread_mutex_unlock(&stop_mutex); - return NULL; - - case C_MEMALIGN: - p2 = get_int (io); - sz2 = get_int (io); - sz = get_int (io); - dprintf("op %p:%ld %ld = MEMALIGN %ld %ld\n", (void *)thrc, io_pos (io), p2, sz2, sz); - /* we can't force memalign to return NULL (fail), so just skip it. */ - if (p2 == 0) - break; - if (p2 > n_ptrs) - myabort(); - stime = rdtsc_s(); - Q1; - if (ptrs[p2]) - { - if (!quick_run) - free ((void *)ptrs[p2]); - atomic_rss (-sizes[p2]); - } - if (!quick_run) - ptrs[p2] = memalign (sz2, sz); - else - ptrs[p2] = (void *)p2; - /* Verify the alignment matches what is expected. */ - if (((size_t)ptrs[p2] & (sz2 - 1)) != 0) - myabort (); - sizes[p2] = sz; - mprintf("%p = memalign(%lx, %lx)\n", ptrs[p2], sz2, sz); - Q2; - etime = rdtsc_e(); - if (ptrs[p2] != NULL) - atomic_rss (sz); - if (etime < stime) - { - printf("s: %llx e:%llx d:%llx\n", (long long)stime, (long long)etime, (long long)(etime-stime)); - } - my_malloc_time += etime - stime; - my_malloc_count ++; - if (!quick_run) - wmem(ptrs[p2], sz); - break; - - case C_MALLOC: - p2 = get_int (io); - sz = get_int (io); - dprintf("op %p:%ld %ld = MALLOC %ld\n", (void *)thrc, io_pos (io), p2, sz); - /* we can't force malloc to return NULL (fail), so just skip it. */ - if (p2 == 0) - break; - if (p2 > n_ptrs) - myabort(); - stime = rdtsc_s(); - Q1; - if (ptrs[p2]) - { - if (!quick_run) - free ((void *)ptrs[p2]); - atomic_rss (-sizes[p2]); - } - if (!quick_run) - ptrs[p2] = malloc (sz); - else - ptrs[p2] = (void *)p2; - sizes[p2] = sz; - mprintf("%p = malloc(%lx)\n", ptrs[p2], sz); - Q2; - etime = rdtsc_e(); - if (ptrs[p2] != NULL) - atomic_rss (sz); - if (etime < stime) - { - printf("s: %llx e:%llx d:%llx\n", (long long)stime, (long long)etime, (long long)(etime-stime)); - } - my_malloc_time += etime - stime; - my_malloc_count ++; - if (!quick_run) - wmem(ptrs[p2], sz); - break; - - case C_CALLOC: - p2 = get_int (io); - sz = get_int (io); - dprintf("op %p:%ld %ld = CALLOC %ld\n", (void *)thrc, io_pos (io), p2, sz); - /* we can't force calloc to return NULL (fail), so just skip it. */ - if (p2 == 0) - break; - if (p2 > n_ptrs) - myabort(); - if (ptrs[p2]) - { - if (!quick_run) - free ((void *)ptrs[p2]); - atomic_rss (-sizes[p2]); - } - stime = rdtsc_s(); - Q1; - if (!quick_run) - ptrs[p2] = calloc (sz, 1); - else - ptrs[p2] = (void *)p2; - sizes[p2] = sz; - mprintf("%p = calloc(%lx)\n", ptrs[p2], sz); - Q2; - if (ptrs[p2]) - atomic_rss (sz); - my_calloc_time += rdtsc_e() - stime; - my_calloc_count ++; - if (!quick_run) - wmem(ptrs[p2], sz); - break; - - case C_REALLOC: - p2 = get_int (io); - p1 = get_int (io); - sz = get_int (io); - dprintf("op %p:%ld %ld = REALLOC %ld %ld\n", (void *)thrc, io_pos (io), p2, p1, sz); - if (p1 > n_ptrs) - myabort(); - if (p2 > n_ptrs) - myabort(); - /* we can't force realloc to return NULL (fail), so just skip it. */ - if (p2 == 0) - break; - - if (ptrs[p1]) - atomic_rss (-sizes[p1]); - if (!quick_run) - free_wipe(p1); - stime = rdtsc_s(); - Q1; -#ifdef MDEBUG - tmp = ptrs[p1]; -#endif - if (!quick_run) - ptrs[p2] = realloc ((void *)ptrs[p1], sz); - else - ptrs[p2] = (void *)p2; - sizes[p2] = sz; - mprintf("%p = relloc(%p,%lx)\n", ptrs[p2], tmp,sz); - Q2; - my_realloc_time += rdtsc_e() - stime; - my_realloc_count ++; - if (!quick_run) - wmem(ptrs[p2], sz); - if (p1 != p2) - ptrs[p1] = 0; - if (ptrs[p2]) - atomic_rss (sizes[p2]); - break; - - case C_FREE: - p1 = get_int (io); - if (p1 > n_ptrs) - myabort(); - dprintf("op %p:%ld FREE %ld\n", (void *)thrc, io_pos (io), p1); - if (!quick_run) - free_wipe (p1); - if (ptrs[p1]) - atomic_rss (-sizes[p1]); - stime = rdtsc_s(); - Q1; - mprintf("free(%p)\n", ptrs[p1]); - if (!quick_run) - free ((void *)ptrs[p1]); - Q2; - my_free_time += rdtsc_e() - stime; - my_free_count ++; - ptrs[p1] = 0; - break; - - case C_SYNC_W: - p1 = get_int(io); - dprintf("op %p:%ld SYNC_W %ld\n", (void *)thrc, io_pos (io), p1); - if (p1 > n_syncs) - myabort(); - pthread_mutex_lock (&mutexes[p1]); - syncs[p1] = 1; - pthread_cond_signal (&conds[p1]); - __sync_synchronize (); - pthread_mutex_unlock (&mutexes[p1]); - break; - - case C_SYNC_R: - p1 = get_int(io); - dprintf("op %p:%ld SYNC_R %ld\n", (void *)thrc, io_pos (io), p1); - if (p1 > n_syncs) - myabort(); - pthread_mutex_lock (&mutexes[p1]); - while (syncs[p1] != 1) - { - pthread_cond_wait (&conds[p1], &mutexes[p1]); - __sync_synchronize (); - } - pthread_mutex_unlock (&mutexes[p1]); - break; - - default: - printf("op %d - unsupported, thread %d addr %lu\n", - this_op, thread_idx, (long unsigned int)io_pos (io)); - myabort(); - } - } -} - -static void *alloc_mem (size_t amt) -{ - void *rv = mmap (NULL, amt, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - mlock (rv, amt); - memset (rv, 0, amt); - return rv; -} - -static pthread_t *thread_ids; - -void * -my_malloc (const char *msg, int size, IOPerThreadType *io, size_t *psz, size_t count) -{ - void *rv; - if (psz) - count = *psz = get_int (io); - dprintf ("my_malloc for %s size %d * %ld\n", msg, size, count); - rv = alloc_mem(size * count); - if (!rv) - { - fprintf(stderr, "calloc(%lu,%lu) failed\n", (long unsigned)size, (long unsigned)*psz); - exit(1); - } - mlock (rv, size * count); - return rv; -} - -static const char * const scan_names[] = { - "UNUSED", - "ARENA", - "HEAP", - "CHUNK_USED", - "CHUNK_FREE", - "FASTBIN_FREE", - "UNSORTED", - "TOP", - "TCACHE", - "USED" -}; - -void -malloc_scan_callback (void *ptr, size_t length, int type) -{ - printf("%s: ptr %p length %llx\n", scan_names[type], ptr, (long long)length); -} - -#define MY_ALLOC(T, psz) \ - (typeof (T)) my_malloc (#T, sizeof(*T), &main_io, psz, 0) -#define MY_ALLOCN(T, count) \ - (typeof (T)) my_malloc (#T, sizeof(*T), &main_io, NULL, count) - -int -main(int argc, char **argv) -{ - ticks_t start=0; - ticks_t end; - ticks_t usec; - struct timeval tv_s, tv_e; - int thread_idx = 0; - int i; - size_t n_threads = 0; - size_t idx; - struct rusage res_start, res_end; - int done; - size_t guessed_io_size = 4096; - struct stat statb; - - if (argc < 2) - { - fprintf(stderr, "Usage: %s <trace2dat.outfile>\n", argv[0]); - exit(1); - } - io_fd = open(argv[1], O_RDONLY); - if (io_fd < 0) - { - fprintf(stderr, "Unable to open %s for reading\n", argv[1]); - perror("The error was"); - exit(1); - } - fstat (io_fd, &statb); - - io_init (&main_io, 0, IOMIN); - - pthread_mutex_lock(&stop_mutex); - - done = 0; - while (!done) - { - switch (io_read (&main_io)) - { - case C_NOP: - break; - case C_ALLOC_PTRS: - ptrs = MY_ALLOC (ptrs, &n_ptrs); - sizes = alloc_mem(sizeof(sizes[0]) * n_ptrs); - ptrs[0] = 0; - break; - case C_ALLOC_SYNCS: - n_syncs = get_int(&main_io); - syncs = MY_ALLOCN (syncs, n_syncs); - conds = MY_ALLOCN (conds, n_syncs); - mutexes = MY_ALLOCN (mutexes, n_syncs); - for (idx=0; idx<n_syncs; idx++) - { - pthread_mutex_init (&mutexes[idx], NULL); - pthread_cond_init (&conds[idx], NULL); - } - break; - case C_NTHREADS: - thread_ids = MY_ALLOC (thread_ids, &n_threads); - thread_io = MY_ALLOCN (thread_io, n_threads); - guessed_io_size = ((statb.st_size / n_threads) < (1024*1024)) ? 65536 : 4096; - /* The next thing in the workscript is thread creation */ - getrusage (RUSAGE_SELF, &res_start); - gettimeofday (&tv_s, NULL); - start = rdtsc_s(); - break; - case C_START_THREAD: - idx = get_int (&main_io); - io_init (& thread_io[thread_idx], idx, guessed_io_size); - pthread_create (&thread_ids[thread_idx], NULL, thread_common, thread_io + thread_idx); - dprintf("Starting thread %lld at offset %lu %lx\n", (long long)thread_ids[thread_idx], (unsigned long)idx, (unsigned long)idx); - thread_idx ++; - break; - case C_DONE: - do - { - pthread_mutex_lock (&stat_mutex); - i = threads_done; - pthread_mutex_unlock (&stat_mutex); - } while (i < thread_idx); - done = 1; - break; - } - } - if (!quick_run) - { - end = rdtsc_e(); - gettimeofday (&tv_e, NULL); - getrusage (RUSAGE_SELF, &res_end); - - printf("%s cycles\n", comma(end - start)); - usec = diff_timeval (tv_e, tv_s); - printf("%s usec wall time\n", comma(usec)); - - usec = diff_timeval (res_end.ru_utime, res_start.ru_utime); - printf("%s usec across %d thread%s\n", - comma(usec), (int)n_threads, n_threads == 1 ? "" : "s"); - printf("%s Kb Max RSS (%s -> %s)\n", - comma(res_end.ru_maxrss - res_start.ru_maxrss), - comma(res_start.ru_maxrss), comma(res_end.ru_maxrss)); - } - printf("%s Kb Max Ideal RSS\n", comma (max_ideal_rss / 1024)); - - if (malloc_count == 0) malloc_count ++; - if (calloc_count == 0) calloc_count ++; - if (realloc_count == 0) realloc_count ++; - if (free_count == 0) free_count ++; - - if (!quick_run) - { - printf("\n"); - printf("sizeof ticks_t is %lu\n", sizeof(ticks_t)); - printf("Avg malloc time: %6s in %10s calls\n", comma(malloc_time/malloc_count), comma(malloc_count)); - printf("Avg calloc time: %6s in %10s calls\n", comma(calloc_time/calloc_count), comma(calloc_count)); - printf("Avg realloc time: %5s in %10s calls\n", comma(realloc_time/realloc_count), comma(realloc_count)); - printf("Avg free time: %8s in %10s calls\n", comma(free_time/free_count), comma(free_count)); - printf("Total call time: %s cycles\n", comma(malloc_time+calloc_time+realloc_time+free_time)); - printf("\n"); - } - -#if 0 - /* Free any still-held chunks of memory. */ - for (idx=0; idx<n_ptrs; idx++) - if (ptrs[idx]) - { - free((void *)ptrs[idx]); - ptrs[idx] = 0; - } -#endif - -#if 0 - /* This will fail (crash) for system glibc but that's OK. */ - __malloc_scan_chunks(malloc_scan_callback); - - malloc_info (0, stdout); -#endif - -#if 0 - /* ...or report them as used. */ - for (idx=0; idx<n_ptrs; idx++) - if (ptrs[idx]) - { - char *p = (char *)ptrs[idx] - 2*sizeof(size_t); - size_t *sp = (size_t *)p; - size_t size = sp[1] & ~7; - malloc_scan_callback (sp, size, 9); - } -#endif - - /* Now that we've scanned all the per-thread caches, it's safe to - let them exit and clean up. */ - pthread_mutex_unlock(&stop_mutex); - - for (i=0; i<thread_idx; i++) - pthread_join (thread_ids[i], NULL); - - return 0; -} diff --git a/src/benchmarks/espresso.py b/src/benchmarks/espresso.py deleted file mode 100644 index 4671822..0000000 --- a/src/benchmarks/espresso.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""espresso is a single threaded programmable logic array analyzer, described by Zorn and Grunwald -their paper "Empirical Measurements of Six Allocation-intensive C Programs" in 1992. - -It is mentioned in: -* Dirk Grunwald et al. - 1992 - CustoMalloc: Efficient Synthesized Memory Allocators -* Dirk Grunwald et al. - 1993 - Improving the Cache Locality of Memory Allocation -* Paul Wilson et al. - 1995 - Dynamic Storage Allocation: A Survey and Critical Review -* Emery Berger et al. - 2000 - Hoard: A Scalable Memory Allocator for Multithreaded Applications -* Emery Berger et al. - 2001 - Composing High-Performance Memory Allocators -* Emery Berger et al. - 2002 - Reconsidering Custom Memory Allocation -* Periklis Akritidis - 2010 - Cling: A Memory Allocator to Mitigate Dangling Pointers -* Daan Leijen et al. - 2019 - Mimalloc: Free List Sharding in Action - -The file "largest.espresso" shipped with mimalloc-bench and allocbench generates -a workload with 3367364 allocator calls (malloc: 1659385, free: 1691851, realloc: 16128). -About 87% of all allocations are smaller than 64 Byte, the common cache line size. - -Allocator portion of total cycles measured using perf record/report: -malloc 8.64% -free 5.04% - -Top 10 allocation sizes 90.73% of all allocations -1. 48 B occurred 615622 times -2. 16 B occurred 533267 times -3. 56 B occurred 235944 times -4. 72 B occurred 27318 times -5. 88 B occurred 23640 times -6. 64 B occurred 22498 times -7. 80 B occurred 17779 times -8. 8 B occurred 16336 times -9. 272 B occurred 14644 times -10. 96 B occurred 13175 times - -allocations <= 64 1442648 86.10% -allocations <= 1024 1657509 98.93% -allocations <= 4096 1667112 99.50% - -The relevant non functional allocator properties are the raw speed of the -API function as well as memory placement strategies with good data locality. -""" - -import os - -from src.benchmark import Benchmark -import src.globalvars -import src.plots as plt - - -class BenchmarkEspresso(Benchmark): - """Definition of the espresso benchmark for allocbench""" - def __init__(self): - name = "espresso" - - self.cmd = "espresso{binary_suffix} {file}" - self.args = { - "file": [ - os.path.join(src.globalvars.benchsrcdir, name, - "largest.espresso") - ] - } - - self.requirements = ["espresso"] - super().__init__(name) - - def summary(self): - # Speed - plt.plot(self, - "{task-clock}/1000", - plot_type='bar', - fig_options={ - 'ylabel': "cpu-second", - 'title': "Espresso: runtime", - }, - file_postfix="time") - - # L1 cache misses - plt.plot(self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - fig_options={ - 'ylabel': "L1 misses in %", - 'title': "Espresso l1 cache misses", - 'yerr': False - }, - file_postfix="l1misses") - - # Memusage - plt.plot(self, - "{VmHWM}", - fig_options={ - 'ylabel': "VmHWM in KB", - 'title': "Espresso VmHWM", - }, - file_postfix="vmhwm") - - plt.write_tex_table(self, [{ - "label": "Runtime [ms]", - "expression": "{task-clock}", - "sort": "<" - }, { - "label": "Memusage [KB]", - "expression": "{VmHWM}", - "sort": "<" - }], - file_postfix="table") - - plt.export_stats_to_dataref(self, "task-clock") - - plt.export_stats_to_dataref(self, "VmHWM") - - -espresso = BenchmarkEspresso() diff --git a/src/benchmarks/espresso/CMakeLists.txt b/src/benchmarks/espresso/CMakeLists.txt deleted file mode 100644 index cc5dac2..0000000 --- a/src/benchmarks/espresso/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(espresso C) -set(CMAKE_CXX_STANDARD 17) - -set(CMAKE_BUILD_TYPE "Release") - -set(espresso_sources - cofactor.c cols.c compl.c contain.c cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c - dominate.c equiv.c espresso.c essen.c exact.c expand.c gasp.c getopt.c gimpel.c - globals.c hack.c indep.c irred.c main.c map.c matrix.c mincov.c opo.c pair.c part.c - primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c unate.c - utility.c verify.c) - -add_executable(espresso ${espresso_sources}) -target_compile_options(espresso PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>) -target_link_libraries(espresso m) - diff --git a/src/benchmarks/espresso/README.md b/src/benchmarks/espresso/README.md deleted file mode 100644 index 7cc0d93..0000000 --- a/src/benchmarks/espresso/README.md +++ /dev/null @@ -1,22 +0,0 @@ -``` -Oct Tools Distribution 4.0 - -Copyright (c) 1988, 1989, 1990, Regents of the University of California. -All rights reserved. - -Use and copying of this software and preparation of derivative works -based upon this software are permitted. However, any distribution of -this software or derivative works must include the above copyright -notice. - -This software is made available AS IS, and neither the Electronics -Research Laboratory or the University of California make any -warranty about the software, its performance or its conformity to -any specification. - -Suggestions, comments, or improvements are welcome and should be -addressed to: - - octtools@eros.berkeley.edu - ..!ucbvax!eros!octtools -``` diff --git a/src/benchmarks/espresso/ansi.h b/src/benchmarks/espresso/ansi.h deleted file mode 100644 index 81e482f..0000000 --- a/src/benchmarks/espresso/ansi.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef ANSI_H -#define ANSI_H - -/* - * ANSI Compiler Support - * - * David Harrison - * University of California, Berkeley - * 1988 - * - * ANSI compatible compilers are supposed to define the preprocessor - * directive __STDC__. Based on this directive, this file defines - * certain ANSI specific macros. - * - * ARGS: - * Used in function prototypes. Example: - * extern int foo - * ARGS((char *blah, double threshold)); - */ - -/* Function prototypes */ -#if defined(__STDC__) || defined(__cplusplus) -#define ARGS(args) args -#else -#define ARGS(args) () -#endif - -#if defined(__cplusplus) -#define NULLARGS (void) -#else -#define NULLARGS () -#endif - -#ifdef __cplusplus -#define EXTERN extern "C" -#else -#define EXTERN extern -#endif - -#if defined(__cplusplus) || defined(__STDC__) -#define HAS_STDARG -#endif - -#endif diff --git a/src/benchmarks/espresso/cofactor.c b/src/benchmarks/espresso/cofactor.c deleted file mode 100644 index e082695..0000000 --- a/src/benchmarks/espresso/cofactor.c +++ /dev/null @@ -1,373 +0,0 @@ -#include "espresso.h" - -/* - The cofactor of a cover against a cube "c" is a cover formed by the - cofactor of each cube in the cover against c. The cofactor of two - cubes is null if they are distance 1 or more apart. If they are - distance zero apart, the cofactor is the restriction of the cube - to the minterms of c. - - The cube list contains the following information: - - T[0] = pointer to a cube identifying the variables that have - been cofactored against - T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case) - T[2] - . - . = pointers to cubes - . - T[n-2] - T[n-1] = NULL pointer (sentinel) - - - Cofactoring involves repeated application of "cdist0" to check if a - cube of the cover intersects the cofactored cube. This can be - slow, especially for the recursive descent of the espresso - routines. Therefore, a special cofactor routine "scofactor" is - provided which assumes the cofactor is only in a single variable. -*/ - - -/* cofactor -- compute the cofactor of a cover with respect to a cube */ -pcube *cofactor(T, c) -IN pcube *T; -IN register pcube c; -{ - pcube temp = cube.temp[0], *Tc_save, *Tc, *T1; - register pcube p; - int listlen; - - listlen = CUBELISTSIZE(T) + 5; - - /* Allocate a new list of cube pointers (max size is previous size) */ - Tc_save = Tc = ALLOC(pcube, listlen); - - /* pass on which variables have been cofactored against */ - *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c)); - Tc++; - - /* Loop for each cube in the list, determine suitability, and save */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (p != c) { - -#ifdef NO_INLINE - if (! cdist0(p, c)) goto false; -#else - {register int w,last;register unsigned int x;if((last=cube.inword)!=-1) - {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto lfalse;for(w=1;w<last;w++) - {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto lfalse;}}}{register int w,var,last; - register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){ - mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var - ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto lfalse;nextvar:;}} -#endif - - *Tc++ = p; - lfalse: ; - } - } - - *Tc++ = (pcube) NULL; /* sentinel */ - Tc_save[1] = (pcube) Tc; /* save pointer to last */ - return Tc_save; -} - -/* - scofactor -- compute the cofactor of a cover with respect to a cube, - where the cube is "active" in only a single variable. - - This routine has been optimized for speed. -*/ - -pcube *scofactor(T, c, var) -IN pcube *T, c; -IN int var; -{ - pcube *Tc, *Tc_save; - register pcube p, mask = cube.temp[1], *T1; - register int first = cube.first_word[var], last = cube.last_word[var]; - int listlen; - - listlen = CUBELISTSIZE(T) + 5; - - /* Allocate a new list of cube pointers (max size is previous size) */ - Tc_save = Tc = ALLOC(pcube, listlen); - - /* pass on which variables have been cofactored against */ - *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c)); - Tc++; - - /* Setup for the quick distance check */ - (void) set_and(mask, cube.var_mask[var], c); - - /* Loop for each cube in the list, determine suitability, and save */ - for(T1 = T+2; (p = *T1++) != NULL; ) - if (p != c) { - register int i = first; - do - if (p[i] & mask[i]) { - *Tc++ = p; - break; - } - while (++i <= last); - } - - *Tc++ = (pcube) NULL; /* sentinel */ - Tc_save[1] = (pcube) Tc; /* save pointer to last */ - return Tc_save; -} - -void massive_count(T) -IN pcube *T; -{ - int *count = cdata.part_zeros; - pcube *T1; - - /* Clear the column counts (count of # zeros in each column) */ - { register int i; - for(i = cube.size - 1; i >= 0; i--) - count[i] = 0; - } - - /* Count the number of zeros in each column */ - { register int i, *cnt; - register unsigned int val; - register pcube p, cof = T[0], full = cube.fullset; - for(T1 = T+2; (p = *T1++) != NULL; ) - for(i = LOOP(p); i > 0; i--) - if (val = full[i] & ~ (p[i] | cof[i])) { - cnt = count + ((i-1) << LOGBPI); -#if BPI == 32 - if (val & 0xFF000000) { - if (val & 0x80000000) cnt[31]++; - if (val & 0x40000000) cnt[30]++; - if (val & 0x20000000) cnt[29]++; - if (val & 0x10000000) cnt[28]++; - if (val & 0x08000000) cnt[27]++; - if (val & 0x04000000) cnt[26]++; - if (val & 0x02000000) cnt[25]++; - if (val & 0x01000000) cnt[24]++; - } - if (val & 0x00FF0000) { - if (val & 0x00800000) cnt[23]++; - if (val & 0x00400000) cnt[22]++; - if (val & 0x00200000) cnt[21]++; - if (val & 0x00100000) cnt[20]++; - if (val & 0x00080000) cnt[19]++; - if (val & 0x00040000) cnt[18]++; - if (val & 0x00020000) cnt[17]++; - if (val & 0x00010000) cnt[16]++; - } -#endif - if (val & 0xFF00) { - if (val & 0x8000) cnt[15]++; - if (val & 0x4000) cnt[14]++; - if (val & 0x2000) cnt[13]++; - if (val & 0x1000) cnt[12]++; - if (val & 0x0800) cnt[11]++; - if (val & 0x0400) cnt[10]++; - if (val & 0x0200) cnt[ 9]++; - if (val & 0x0100) cnt[ 8]++; - } - if (val & 0x00FF) { - if (val & 0x0080) cnt[ 7]++; - if (val & 0x0040) cnt[ 6]++; - if (val & 0x0020) cnt[ 5]++; - if (val & 0x0010) cnt[ 4]++; - if (val & 0x0008) cnt[ 3]++; - if (val & 0x0004) cnt[ 2]++; - if (val & 0x0002) cnt[ 1]++; - if (val & 0x0001) cnt[ 0]++; - } - } - } - - /* - * Perform counts for each variable: - * cdata.var_zeros[var] = number of zeros in the variable - * cdata.parts_active[var] = number of active parts for each variable - * cdata.vars_active = number of variables which are active - * cdata.vars_unate = number of variables which are active and unate - * - * best -- the variable which is best for splitting based on: - * mostactive -- most # active parts in any variable - * mostzero -- most # zeros in any variable - * mostbalanced -- minimum over the maximum # zeros / part / variable - */ - - { register int var, i, lastbit, active, maxactive; - int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000; - cdata.vars_unate = cdata.vars_active = 0; - - for(var = 0; var < cube.num_vars; var++) { - if (var < cube.num_binary_vars) { /* special hack for binary vars */ - i = count[var*2]; - lastbit = count[var*2 + 1]; - active = (i > 0) + (lastbit > 0); - cdata.var_zeros[var] = i + lastbit; - maxactive = MAX(i, lastbit); - } else { - maxactive = active = cdata.var_zeros[var] = 0; - lastbit = cube.last_part[var]; - for(i = cube.first_part[var]; i <= lastbit; i++) { - cdata.var_zeros[var] += count[i]; - active += (count[i] > 0); - if (active > maxactive) maxactive = active; - } - } - - /* first priority is to maximize the number of active parts */ - /* for binary case, this will usually select the output first */ - if (active > mostactive) - best = var, mostactive = active, mostzero = cdata.var_zeros[best], - mostbalanced = maxactive; - else if (active == mostactive) - /* secondary condition is to maximize the number zeros */ - /* for binary variables, this is the same as minimum # of 2's */ - if (cdata.var_zeros[var] > mostzero) - best = var, mostzero = cdata.var_zeros[best], - mostbalanced = maxactive; - else if (cdata.var_zeros[var] == mostzero) - /* third condition is to pick a balanced variable */ - /* for binary vars, this means roughly equal # 0's and 1's */ - if (maxactive < mostbalanced) - best = var, mostbalanced = maxactive; - - cdata.parts_active[var] = active; - cdata.is_unate[var] = (active == 1); - cdata.vars_active += (active > 0); - cdata.vars_unate += (active == 1); - } - cdata.best = best; - } -} - -int binate_split_select(T, cleft, cright, debug_flag) -IN pcube *T; -IN register pcube cleft, cright; -IN int debug_flag; -{ - int best = cdata.best; - register int i, lastbit = cube.last_part[best], halfbit = 0; - register pcube cof=T[0]; - - /* Create the cubes to cofactor against */ - set_diff(cleft, cube.fullset, cube.var_mask[best]); - set_diff(cright, cube.fullset, cube.var_mask[best]); - for(i = cube.first_part[best]; i <= lastbit; i++) - if (! is_in_set(cof,i)) - halfbit++; - for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++) - if (! is_in_set(cof,i)) - halfbit--, set_insert(cleft, i); - for(; i <= lastbit; i++) - if (! is_in_set(cof,i)) - set_insert(cright, i); - - if (debug & debug_flag) { - printf("BINATE_SPLIT_SELECT: split against %d\n", best); - if (verbose_debug) - printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright)); - } - return best; -} - - -pcube *cube1list(A) -pcover A; -{ - register pcube last, p, *plist, *list; - - list = plist = ALLOC(pcube, A->count + 3); - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - *plist++ = NULL; /* sentinel */ - list[1] = (pcube) plist; - return list; -} - - -pcube *cube2list(A, B) -pcover A, B; -{ - register pcube last, p, *plist, *list; - - list = plist = ALLOC(pcube, A->count + B->count + 3); - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - foreach_set(B, last, p) { - *plist++ = p; - } - *plist++ = NULL; - list[1] = (pcube) plist; - return list; -} - - -pcube *cube3list(A, B, C) -pcover A, B, C; -{ - register pcube last, p, *plist, *list; - - plist = ALLOC(pcube, A->count + B->count + C->count + 3); - list = plist; - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - foreach_set(B, last, p) { - *plist++ = p; - } - foreach_set(C, last, p) { - *plist++ = p; - } - *plist++ = NULL; - list[1] = (pcube) plist; - return list; -} - - -pcover cubeunlist(A1) -pcube *A1; -{ - register int i; - register pcube p, pdest, cof = A1[0]; - register pcover A; - - A = new_cover(CUBELISTSIZE(A1)); - for(i = 2; (p = A1[i]) != NULL; i++) { - pdest = GETSET(A, i-2); - INLINEset_or(pdest, p, cof); - } - A->count = CUBELISTSIZE(A1); - return A; -} - -simplify_cubelist(T) -pcube *T; -{ - register pcube *Tdest; - register int i, ncubes; - - set_copy(cube.temp[0], T[0]); /* retrieve cofactor */ - - ncubes = CUBELISTSIZE(T); - qsort((char *) (T+2), ncubes, sizeof(pset), d1_order); - - Tdest = T+2; - /* *Tdest++ = T[2]; */ - for(i = 3; i < ncubes; i++) { - if (d1_order(&T[i-1], &T[i]) != 0) { - *Tdest++ = T[i]; - } - } - - *Tdest++ = NULL; /* sentinel */ - Tdest[1] = (pcube) Tdest; /* save pointer to last */ -} diff --git a/src/benchmarks/espresso/cols.c b/src/benchmarks/espresso/cols.c deleted file mode 100644 index 0bfa160..0000000 --- a/src/benchmarks/espresso/cols.c +++ /dev/null @@ -1,306 +0,0 @@ -#include "espresso.h" -#include "port.h" -#include "sparse_int.h" - - -/* - * allocate a new col vector - */ -sm_col * -sm_col_alloc() -{ - register sm_col *pcol; - -#ifdef FAST_AND_LOOSE - if (sm_col_freelist == NIL(sm_col)) { - pcol = ALLOC(sm_col, 1); - } else { - pcol = sm_col_freelist; - sm_col_freelist = pcol->next_col; - } -#else - pcol = ALLOC(sm_col, 1); -#endif - - pcol->col_num = 0; - pcol->length = 0; - pcol->first_row = pcol->last_row = NIL(sm_element); - pcol->next_col = pcol->prev_col = NIL(sm_col); - pcol->flag = 0; - pcol->user_word = NIL(char); /* for our user ... */ - return pcol; -} - - -/* - * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols; - * however, freeing a rowumn must still walk down the rowumn discarding - * the elements one-by-one; that is the only use for the extra '-DCOLS' - * compile flag ... - */ -void -sm_col_free(pcol) -register sm_col *pcol; -{ -#if defined(FAST_AND_LOOSE) && ! defined(COLS) - if (pcol->first_row != NIL(sm_element)) { - /* Add the linked list of col items to the free list */ - pcol->last_row->next_row = sm_element_freelist; - sm_element_freelist = pcol->first_row; - } - - /* Add the col to the free list of cols */ - pcol->next_col = sm_col_freelist; - sm_col_freelist = pcol; -#else - register sm_element *p, *pnext; - - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; - sm_element_free(p); - } - FREE(pcol); -#endif -} - - -/* - * duplicate an existing col - */ -sm_col * -sm_col_dup(pcol) -register sm_col *pcol; -{ - register sm_col *pnew; - register sm_element *p; - - pnew = sm_col_alloc(); - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) sm_col_insert(pnew, p->row_num); - } - return pnew; -} - - -/* - * insert an element into a col vector - */ -sm_element * -sm_col_insert(pcol, row) -register sm_col *pcol; -register int row; -{ - register sm_element *test, *element; - - /* get a new item, save its address */ - sm_element_alloc(element); - test = element; - sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, - next_row, prev_row, row_num, row, test); - - /* if item was not used, free it */ - if (element != test) { - sm_element_free(element); - } - - /* either way, return the current new value */ - return test; -} - - -/* - * remove an element from a col vector - */ -void -sm_col_remove(pcol, row) -register sm_col *pcol; -register int row; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) - ; - if (p != 0 && p->row_num == row) { - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - sm_element_free(p); - } -} - - -/* - * find an element (if it is in the col vector) - */ -sm_element * -sm_col_find(pcol, row) -sm_col *pcol; -int row; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) - ; - if (p != 0 && p->row_num == row) { - return p; - } else { - return NIL(sm_element); - } -} - -/* - * return 1 if col p2 contains col p1; 0 otherwise - */ -int -sm_col_contains(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - while (q1 != 0) { - if (q2 == 0 || q1->row_num < q2->row_num) { - return 0; - } else if (q1->row_num == q2->row_num) { - q1 = q1->next_row; - q2 = q2->next_row; - } else { - q2 = q2->next_row; - } - } - return 1; -} - - -/* - * return 1 if col p1 and col p2 share an element in common - */ -int -sm_col_intersects(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - if (q1 == 0 || q2 == 0) return 0; - for(;;) { - if (q1->row_num < q2->row_num) { - if ((q1 = q1->next_row) == 0) { - return 0; - } - } else if (q1->row_num > q2->row_num) { - if ((q2 = q2->next_row) == 0) { - return 0; - } - } else { - return 1; - } - } -} - - -/* - * compare two cols, lexical ordering - */ -int -sm_col_compare(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - while(q1 != 0 && q2 != 0) { - if (q1->row_num != q2->row_num) { - return q1->row_num - q2->row_num; - } - q1 = q1->next_row; - q2 = q2->next_row; - } - - if (q1 != 0) { - return 1; - } else if (q2 != 0) { - return -1; - } else { - return 0; - } -} - - -/* - * return the intersection - */ -sm_col * -sm_col_and(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - register sm_col *result; - - result = sm_col_alloc(); - q1 = p1->first_row; - q2 = p2->first_row; - if (q1 == 0 || q2 == 0) return result; - for(;;) { - if (q1->row_num < q2->row_num) { - if ((q1 = q1->next_row) == 0) { - return result; - } - } else if (q1->row_num > q2->row_num) { - if ((q2 = q2->next_row) == 0) { - return result; - } - } else { - (void) sm_col_insert(result, q1->row_num); - if ((q1 = q1->next_row) == 0) { - return result; - } - if ((q2 = q2->next_row) == 0) { - return result; - } - } - } -} - -int -sm_col_hash(pcol, modulus) -sm_col *pcol; -int modulus; -{ - register int sum; - register sm_element *p; - - sum = 0; - for(p = pcol->first_row; p != 0; p = p->next_row) { - sum = (sum*17 + p->row_num) % modulus; - } - return sum; -} - -/* - * remove an element from a col vector (given a pointer to the element) - */ -void -sm_col_remove_element(pcol, p) -register sm_col *pcol; -register sm_element *p; -{ - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - sm_element_free(p); -} - - -void -sm_col_print(fp, pcol) -FILE *fp; -sm_col *pcol; -{ - sm_element *p; - - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) fprintf(fp, " %d", p->row_num); - } -} diff --git a/src/benchmarks/espresso/compl.c b/src/benchmarks/espresso/compl.c deleted file mode 100644 index d0db019..0000000 --- a/src/benchmarks/espresso/compl.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * module: compl.c - * purpose: compute the complement of a multiple-valued function - * - * The "unate recursive paradigm" is used. After a set of special - * cases are examined, the function is split on the "most active - * variable". These two halves are complemented recursively, and then - * the results are merged. - * - * Changes (from Version 2.1 to Version 2.2) - * 1. Minor bug in compl_lifting -- cubes in the left half were - * not marked as active, so that when merging a leaf from the left - * hand side, the active flags were essentially random. This led - * to minor impredictability problem, but never affected the - * accuracy of the results. - */ - -#include "espresso.h" - -#define USE_COMPL_LIFT 0 -#define USE_COMPL_LIFT_ONSET 1 -#define USE_COMPL_LIFT_ONSET_COMPLEX 2 -#define NO_LIFTING 3 - -static bool compl_special_cases(); -static pcover compl_merge(); -static void compl_d1merge(); -static pcover compl_cube(); -static void compl_lift(); -static void compl_lift_onset(); -static void compl_lift_onset_complex(); -static bool simp_comp_special_cases(); -static bool simplify_special_cases(); - - -/* complement -- compute the complement of T */ -pcover complement(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tbar, Tl, Tr; - int lifting; - static int compl_level = 0; - - if (debug & COMPL) - debug_print(T, "COMPLEMENT", compl_level++); - - if (compl_special_cases(T, &Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - Tl = complement(scofactor(T, cl, best)); - Tr = complement(scofactor(T, cr, best)); - - if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) { - lifting = USE_COMPL_LIFT_ONSET; - } else { - lifting = USE_COMPL_LIFT; - } - Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) - debug1_print(Tbar, "exit COMPLEMENT", --compl_level); - return Tbar; -} - -static bool compl_special_cases(T, Tbar) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tbar; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcover A, ceil_compl; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tbar = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tbar = compl_cube(set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies complement is null) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tbar = new_cover(0); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - ceil_compl = compl_cube(ceil); - (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil)); - set_free(ceil); - *Tbar = sf_append(complement(T), ceil_compl); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tbar = new_cover(0); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = map_cover_to_unate(T); - free_cubelist(T); - A = unate_compl(A); - *Tbar = map_unate_to_cover(A); - sf_free(A); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -/* - * compl_merge -- merge the two cofactors around the splitting - * variable - * - * The merge operation involves intersecting each cube of the left - * cofactor with cl, and intersecting each cube of the right cofactor - * with cr. The union of these two covers is the merged result. - * - * In order to reduce the number of cubes, a distance-1 merge is - * performed (note that two cubes can only combine distance-1 in the - * splitting variable). Also, a simple expand is performed in the - * splitting variable (simple implies the covering check for the - * expansion is not full containment, but single-cube containment). - */ - -static pcover compl_merge(T1, L, R, cl, cr, var, lifting) -pcube *T1; /* Original ON-set */ -pcover L, R; /* Complement from each recursion branch */ -register pcube cl, cr; /* cubes used for cofactoring */ -int var; /* splitting variable */ -int lifting; /* whether to perform lifting or not */ -{ - register pcube p, last, pt; - pcover T, Tbar; - pcube *L1, *R1; - - if (debug & COMPL) { - printf("compl_merge: left %d, right %d\n", L->count, R->count); - printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr)); - cprint(L); - printf("Right is\n"); - cprint(R); - } - - /* Intersect each cube with the cofactored cube */ - foreach_set(L, last, p) { - INLINEset_and(p, p, cl); - SET(p, ACTIVE); - } - foreach_set(R, last, p) { - INLINEset_and(p, p, cr); - SET(p, ACTIVE); - } - - /* Sort the arrays for a distance-1 merge */ - (void) set_copy(cube.temp[0], cube.var_mask[var]); - qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), d1_order); - qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), d1_order); - - /* Perform distance-1 merge */ - compl_d1merge(L1, R1); - - /* Perform lifting */ - switch(lifting) { - case USE_COMPL_LIFT_ONSET: - T = cubeunlist(T1); - compl_lift_onset(L1, T, cr, var); - compl_lift_onset(R1, T, cl, var); - free_cover(T); - break; - case USE_COMPL_LIFT_ONSET_COMPLEX: - T = cubeunlist(T1); - compl_lift_onset_complex(L1, T, var); - compl_lift_onset_complex(R1, T, var); - free_cover(T); - break; - case USE_COMPL_LIFT: - compl_lift(L1, R1, cr, var); - compl_lift(R1, L1, cl, var); - break; - case NO_LIFTING: - break; - } - FREE(L1); - FREE(R1); - - /* Re-create the merged cover */ - Tbar = new_cover(L->count + R->count); - pt = Tbar->data; - foreach_set(L, last, p) { - INLINEset_copy(pt, p); - Tbar->count++; - pt += Tbar->wsize; - } - foreach_active_set(R, last, p) { - INLINEset_copy(pt, p); - Tbar->count++; - pt += Tbar->wsize; - } - - if (debug & COMPL) { - printf("Result %d\n", Tbar->count); - if (verbose_debug) - cprint(Tbar); - } - - free_cover(L); - free_cover(R); - return Tbar; -} - -/* - * compl_lift_simple -- expand in the splitting variable using single - * cube containment against the other recursion branch to check - * validity of the expansion, and expanding all (or none) of the - * splitting variable. - */ -static void compl_lift(A1, B1, bcube, var) -pcube *A1, *B1, bcube; -int var; -{ - register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5]; - pcube mask = cube.var_mask[var]; - - (void) set_and(liftor, bcube, mask); - - /* for each cube in the first array ... */ - for(; (a = *A1++) != NULL; ) { - if (TESTP(a, ACTIVE)) { - - /* create a lift of this cube in the merging coord */ - (void) set_merge(lift, bcube, a, mask); - - /* for each cube in the second array */ - for(B2 = B1; (b = *B2++) != NULL; ) { - INLINEsetp_implies(lift, b, /* when_false => */ continue); - /* when_true => fall through to next statement */ - - /* cube of A1 was contained by some cube of B1, so raise */ - INLINEset_or(a, a, liftor); - break; - } - } - } -} - - - -/* - * compl_lift_onset -- expand in the splitting variable using a - * distance-1 check against the original on-set; expand all (or - * none) of the splitting variable. Each cube of A1 is expanded - * against the original on-set T. - */ -static void compl_lift_onset(A1, T, bcube, var) -pcube *A1; -pcover T; -pcube bcube; -int var; -{ - register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var]; - - /* for each active cube from one branch of the complement */ - for(; (a = *A1++) != NULL; ) { - if (TESTP(a, ACTIVE)) { - - /* create a lift of this cube in the merging coord */ - INLINEset_and(lift, bcube, mask); /* isolate parts to raise */ - INLINEset_or(lift, a, lift); /* raise these parts in a */ - - /* for each cube in the ON-set, check for intersection */ - foreach_set(T, last, p) { - if (cdist0(p, lift)) { - goto nolift; - } - } - INLINEset_copy(a, lift); /* save the raising */ - SET(a, ACTIVE); -nolift : ; - } - } -} - -/* - * compl_lift_complex -- expand in the splitting variable, but expand all - * parts which can possibly expand. - * T is the original ON-set - * A1 is either the left or right cofactor - */ -static void compl_lift_onset_complex(A1, T, var) -pcube *A1; /* array of pointers to new result */ -pcover T; /* original ON-set */ -int var; /* which variable we split on */ -{ - register int dist; - register pcube last, p, a, xlower; - - /* for each cube in the complement */ - xlower = new_cube(); - for(; (a = *A1++) != NULL; ) { - - if (TESTP(a, ACTIVE)) { - - /* Find which parts of the splitting variable are forced low */ - INLINEset_clear(xlower, cube.size); - foreach_set(T, last, p) { - if ((dist = cdist01(p, a)) < 2) { - if (dist == 0) { - fatal("compl: ON-set and OFF-set are not orthogonal"); - } else { - (void) force_lower(xlower, p, a); - } - } - } - - (void) set_diff(xlower, cube.var_mask[var], xlower); - (void) set_or(a, a, xlower); - free_cube(xlower); - } - } -} - - - -/* - * compl_d1merge -- distance-1 merge in the splitting variable - */ -static void compl_d1merge(L1, R1) -register pcube *L1, *R1; -{ - register pcube pl, pr; - - /* Find equal cubes between the two cofactors */ - for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); ) - switch (d1_order(L1, R1)) { - case 1: - pr = *(++R1); break; /* advance right pointer */ - case -1: - pl = *(++L1); break; /* advance left pointer */ - case 0: - RESET(pr, ACTIVE); - INLINEset_or(pl, pl, pr); - pr = *(++R1); - } -} - - - -/* compl_cube -- return the complement of a single cube (De Morgan's law) */ -static pcover compl_cube(p) -register pcube p; -{ - register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset; - int var; - pcover R; - - /* Allocate worst-case size cover (to avoid checking overflow) */ - R = new_cover(cube.num_vars); - - /* Compute bit-wise complement of the cube */ - INLINEset_diff(diff, full, p); - - for(var = 0; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - /* If the bit-wise complement is not empty in var ... */ - if (! setp_disjoint(diff, mask)) { - pdest = GETSET(R, R->count++); - INLINEset_merge(pdest, diff, full, mask); - } - } - return R; -} - -/* simp_comp -- quick simplification of T */ -void simp_comp(T, Tnew, Tbar) -pcube *T; /* T will be disposed of */ -pcover *Tnew; -pcover *Tbar; -{ - register pcube cl, cr; - register int best; - pcover Tl, Tr, Tlbar, Trbar; - int lifting; - static int simplify_level = 0; - - if (debug & COMPL) - debug_print(T, "SIMPCOMP", simplify_level++); - - if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - simp_comp(scofactor(T, cl, best), &Tl, &Tlbar); - simp_comp(scofactor(T, cr, best), &Tr, &Trbar); - - lifting = USE_COMPL_LIFT; - *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - lifting = USE_COMPL_LIFT; - *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting); - - /* All of this work for nothing ? Let's hope not ... */ - if ((*Tnew)->count > CUBELISTSIZE(T)) { - sf_free(*Tnew); - *Tnew = cubeunlist(T); - } - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) { - debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level); - debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level); - simplify_level--; - } -} - -static bool simp_comp_special_cases(T, Tnew, Tbar) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -pcover *Tbar; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover (function is empty) */ - if (T[2] == NULL) { - *Tnew = new_cover(1); - *Tbar = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - (void) set_or(cof, cof, T[2]); - *Tnew = sf_addset(new_cover(1), cof); - *Tbar = compl_cube(cof); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - *Tbar = new_cover(1); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - set_free(p); - simp_comp(T, Tnew, Tbar); - - /* Adjust the ON-set */ - A = *Tnew; - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - - /* Compute the new complement */ - *Tbar = sf_append(*Tbar, compl_cube(ceil)); - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - *Tbar = new_cover(1); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - /* Make the cover minimum by single-cube containment */ - A = cubeunlist(T); - *Tnew = sf_contain(A); - - /* Now form a minimum representation of the complement */ - A = map_cover_to_unate(T); - A = unate_compl(A); - *Tbar = map_unate_to_cover(A); - sf_free(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -/* simplify -- quick simplification of T */ -pcover simplify(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tbar, Tl, Tr; - int lifting; - static int simplify_level = 0; - - if (debug & COMPL) { - debug_print(T, "SIMPLIFY", simplify_level++); - } - - if (simplify_special_cases(T, &Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - Tl = simplify(scofactor(T, cl, best)); - Tr = simplify(scofactor(T, cr, best)); - - lifting = USE_COMPL_LIFT; - Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - /* All of this work for nothing ? Let's hope not ... */ - if (Tbar->count > CUBELISTSIZE(T)) { - sf_free(Tbar); - Tbar = cubeunlist(T); - } - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) { - debug1_print(Tbar, "exit SIMPLIFY", --simplify_level); - } - return Tbar; -} - -static bool simplify_special_cases(T, Tnew) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tnew = new_cover(0); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - free_cube(p); - - A = simplify(T); - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - *Tnew = A; - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = cubeunlist(T); - *Tnew = sf_contain(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} diff --git a/src/benchmarks/espresso/contain.c b/src/benchmarks/espresso/contain.c deleted file mode 100644 index 6b9c644..0000000 --- a/src/benchmarks/espresso/contain.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - contain.c -- set containment routines - - These are complex routines for performing containment over a - family of sets, but they have the advantage of being much faster - than a straightforward n*n routine. - - First the cubes are sorted by size, and as a secondary key they are - sorted so that if two cubes are equal they end up adjacent. We can - than quickly remove equal cubes from further consideration by - comparing each cube to its neighbor. Finally, because the cubes - are sorted by size, we need only check cubes which are larger (or - smaller) than a given cube for containment. -*/ - -#include "espresso.h" - - -/* - sf_contain -- perform containment on a set family (delete sets which - are contained by some larger set in the family). No assumptions are - made about A, and the result will be returned in decreasing order of - set size. -*/ -pset_family sf_contain(A) -INOUT pset_family A; /* disposes of A */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort into descending order */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - cnt = rm_contain(A1); /* remove contained sets */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_rev_contain -- perform containment on a set family (delete sets which - contain some smaller set in the family). No assumptions are made about - A, and the result will be returned in increasing order of set size -*/ -pset_family sf_rev_contain(A) -INOUT pset_family A; /* disposes of A */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, ascend); /* sort into ascending order */ - cnt = rm_equal(A1, ascend); /* remove duplicates */ - cnt = rm_rev_contain(A1); /* remove containing sets */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_ind_contain -- perform containment on a set family (delete sets which - are contained by some larger set in the family). No assumptions are - made about A, and the result will be returned in decreasing order of - set size. Also maintains a set of row_indices to track which rows - disappear and how the rows end up permuted. -*/ -pset_family sf_ind_contain(A, row_indices) -INOUT pset_family A; /* disposes of A */ -INOUT int *row_indices; /* updated with the new values */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort into descending order */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - cnt = rm_contain(A1); /* remove contained sets */ - R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data); - sf_free(A); - return R; -} - - -/* sf_dupl -- delete duplicate sets in a set family */ -pset_family sf_dupl(A) -INOUT pset_family A; /* disposes of A */ -{ - register int cnt; - register pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort the set family */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_union -- form the contained union of two set families (delete - sets which are contained by some larger set in the family). A and - B are assumed already sorted in decreasing order of set size (and - the SIZE field is assumed to contain the set size), and the result - will be returned sorted likewise. -*/ -pset_family sf_union(A, B) -INOUT pset_family A, B; /* disposes of A and B */ -{ - int cnt; - pset_family R; - pset *A1 = sf_list(A), *B1 = sf_list(B), *E1; - - E1 = ALLOC(pset, MAX(A->count, B->count) + 1); - cnt = rm2_equal(A1, B1, E1, descend); - cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1); - R = sf_merge(A1, B1, E1, cnt, A->sf_size); - sf_free(A); sf_free(B); - return R; -} - - -/* - dist_merge -- consider all sets to be "or"-ed with "mask" and then - delete duplicates from the set family. -*/ -pset_family dist_merge(A, mask) -INOUT pset_family A; /* disposes of A */ -IN pset mask; /* defines variables to mask out */ -{ - pset *A1; - int cnt; - pset_family R; - - set_copy(cube.temp[0], mask); - A1 = sf_sort(A, d1_order); - cnt = d1_rm_equal(A1, d1_order); - R = sf_unlist(A1, cnt, A->sf_size); - sf_free(A); - return R; -} - - -/* - d1merge -- perform an efficient distance-1 merge of cubes of A -*/ -pset_family d1merge(A, var) -INOUT pset_family A; /* disposes of A */ -IN int var; -{ - return dist_merge(A, cube.var_mask[var]); -} - - - -/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */ -int d1_rm_equal(A1, compare) -register pset *A1; /* array of set pointers */ -int (*compare)(); /* comparison function */ -{ - register int i, j, dest; - - dest = 0; - if (A1[0] != (pcube) NULL) { - for(i = 0, j = 1; A1[j] != (pcube) NULL; j++) - if ( (*compare)(&A1[i], &A1[j]) == 0) { - /* if sets are equal (under the mask) merge them */ - set_or(A1[i], A1[i], A1[j]); - } else { - /* sets are unequal, so save the set i */ - A1[dest++] = A1[i]; - i = j; - } - A1[dest++] = A1[i]; - } - A1[dest] = (pcube) NULL; - return dest; -} - - -/* rm_equal -- scan a sorted array of set pointers for duplicate sets */ -int rm_equal(A1, compare) -INOUT pset *A1; /* updated in place */ -IN int (*compare)(); -{ - register pset *p, *pdest = A1; - - if (*A1 != NULL) { /* If more than one set */ - for(p = A1+1; *p != NULL; p++) - if ((*compare)(p, p-1) != 0) - *pdest++ = *(p-1); - *pdest++ = *(p-1); - *pdest = NULL; - } - return pdest - A1; -} - - -/* rm_contain -- perform containment over a sorted array of set pointers */ -int rm_contain(A1) -INOUT pset *A1; /* updated in place */ -{ - register pset *pa, *pb, *pcheck, a, b; - pset *pdest = A1; - int last_size = -1; - - /* Loop for all cubes of A1 */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* Update the check pointer if the size has changed */ - if (SIZE(a) != last_size) - last_size = SIZE(a), pcheck = pdest; - for(pb = A1; pb != pcheck; ) { - b = *pb++; - INLINEsetp_implies(a, b, /* when_false => */ continue); - goto lnext1; - } - /* set a was not contained by some larger set, so save it */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; - return pdest - A1; -} - - -/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */ -int rm_rev_contain(A1) -INOUT pset *A1; /* updated in place */ -{ - register pset *pa, *pb, *pcheck, a, b; - pset *pdest = A1; - int last_size = -1; - - /* Loop for all cubes of A1 */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* Update the check pointer if the size has changed */ - if (SIZE(a) != last_size) - last_size = SIZE(a), pcheck = pdest; - for(pb = A1; pb != pcheck; ) { - b = *pb++; - INLINEsetp_implies(b, a, /* when_false => */ continue); - goto lnext1; - } - /* the set a did not contain some smaller set, so save it */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; - return pdest - A1; -} - - -/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */ -int rm2_equal(A1, B1, E1, compare) -INOUT register pset *A1, *B1; /* updated in place */ -OUT pset *E1; -IN int (*compare)(); -{ - register pset *pda = A1, *pdb = B1, *pde = E1; - - /* Walk through the arrays advancing pointer to larger cube */ - for(; *A1 != NULL && *B1 != NULL; ) - switch((*compare)(A1, B1)) { - case -1: /* "a" comes before "b" */ - *pda++ = *A1++; break; - case 0: /* equal cubes */ - *pde++ = *A1++; B1++; break; - case 1: /* "a" is to follow "b" */ - *pdb++ = *B1++; break; - } - - /* Finish moving down the pointers of A and B */ - while (*A1 != NULL) - *pda++ = *A1++; - while (*B1 != NULL) - *pdb++ = *B1++; - *pda = *pdb = *pde = NULL; - - return pde - E1; -} - - -/* rm2_contain -- perform containment between two arrays of set pointers */ -int rm2_contain(A1, B1) -INOUT pset *A1; /* updated in place */ -IN pset *B1; /* unchanged */ -{ - register pset *pa, *pb, a, b, *pdest = A1; - - /* for each set in the first array ... */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* for each set in the second array which is larger ... */ - for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) { - INLINEsetp_implies(a, b, /* when_false => */ continue); - /* set was contained in some set of B, so don't save pointer */ - goto lnext1; - } - /* set wasn't contained in any set of B, so save the pointer */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; /* sentinel */ - return pdest - A1; /* # elements in A1 */ -} - - - -/* sf_sort -- sort the sets of A */ -pset *sf_sort(A, compare) -IN pset_family A; -IN int (*compare)(); -{ - register pset p, last, *pdest, *A1; - - /* Create a single array pointing to each cube of A */ - pdest = A1 = ALLOC(pset, A->count + 1); - foreach_set(A, last, p) { - PUTSIZE(p, set_ord(p)); /* compute the set size */ - *pdest++ = p; /* save the pointer */ - } - *pdest = NULL; /* Sentinel -- never seen by sort */ - - /* Sort cubes by size */ - qsort((char *) A1, A->count, sizeof(pset), compare); - return A1; -} - - -/* sf_list -- make a list of pointers to the sets in a set family */ -pset *sf_list(A) -IN register pset_family A; -{ - register pset p, last, *pdest, *A1; - - /* Create a single array pointing to each cube of A */ - pdest = A1 = ALLOC(pset, A->count + 1); - foreach_set(A, last, p) - *pdest++ = p; /* save the pointer */ - *pdest = NULL; /* Sentinel */ - return A1; -} - - -/* sf_unlist -- make a set family out of a list of pointers to sets */ -pset_family sf_unlist(A1, totcnt, size) -IN pset *A1; -IN int totcnt, size; -{ - register pset pr, p, *pa; - pset_family R = sf_new(totcnt, size); - - R->count = totcnt; - for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize) - INLINEset_copy(pr, p); - FREE(A1); - return R; -} - - -/* sf_ind_unlist -- make a set family out of a list of pointers to sets */ -pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst) -IN pset *A1; -IN int totcnt, size; -INOUT int *row_indices; -IN register pset pfirst; -{ - register pset pr, p, *pa; - register int i, *new_row_indices; - pset_family R = sf_new(totcnt, size); - - R->count = totcnt; - new_row_indices = ALLOC(int, totcnt); - for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) { - INLINEset_copy(pr, p); - new_row_indices[i] = row_indices[(p - pfirst)/R->wsize]; - } - for(i = 0; i < totcnt; i++) - row_indices[i] = new_row_indices[i]; - FREE(new_row_indices); - FREE(A1); - return R; -} - - -/* sf_merge -- merge three sorted lists of set pointers */ -pset_family sf_merge(A1, B1, E1, totcnt, size) -INOUT pset *A1, *B1, *E1; /* will be disposed of */ -IN int totcnt, size; -{ - register pset pr, ps, *pmin, *pmid, *pmax; - pset_family R; - pset *temp[3], *swap; - int i, j, n; - - /* Allocate the result set_family */ - R = sf_new(totcnt, size); - R->count = totcnt; - pr = R->data; - - /* Quick bubble sort to order the top member of the three arrays */ - n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1; - for(i = 0; i < n-1; i++) - for(j = i+1; j < n; j++) - if (desc1(*temp[i], *temp[j]) > 0) { - swap = temp[j]; - temp[j] = temp[i]; - temp[i] = swap; - } - pmin = temp[0]; pmid = temp[1]; pmax = temp[2]; - - /* Save the minimum element, then update pmin, pmid, pmax */ - while (*pmin != (pset) NULL) { - ps = *pmin++; - INLINEset_copy(pr, ps); - pr += R->wsize; - if (desc1(*pmin, *pmax) > 0) { - swap = pmax; pmax = pmin; pmin = pmid; pmid = swap; - } else if (desc1(*pmin, *pmid) > 0) { - swap = pmin; pmin = pmid; pmid = swap; - } - } - - FREE(A1); - FREE(B1); - FREE(E1); - return R; -} diff --git a/src/benchmarks/espresso/copyright.h b/src/benchmarks/espresso/copyright.h deleted file mode 100644 index 49c2f0b..0000000 --- a/src/benchmarks/espresso/copyright.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef OCTTOOLS_COPYRIGHT_H -#define OCTTOOLS_COPYRIGHT_H -/* - * Oct Tools Distribution 4.0 - * - * Copyright (c) 1988, 1989, 1990, Regents of the University of California. - * All rights reserved. - * - * Use and copying of this software and preparation of derivative works - * based upon this software are permitted. However, any distribution of - * this software or derivative works must include the above copyright - * notice. - * - * This software is made available AS IS, and neither the Electronics - * Research Laboratory or the University of California make any - * warranty about the software, its performance or its conformity to - * any specification. - * - * Suggestions, comments, or improvements are welcome and should be - * addressed to: - * - * octtools@eros.berkeley.edu - * ..!ucbvax!eros!octtools - */ - -#if !defined(lint) && !defined(SABER) -static char octtools_copyright[] = "Copyright (c) 1988, 1989, Regents of the University of California. All rights reserved."; -#endif -#endif diff --git a/src/benchmarks/espresso/cubestr.c b/src/benchmarks/espresso/cubestr.c deleted file mode 100644 index 93ca911..0000000 --- a/src/benchmarks/espresso/cubestr.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - Module: cubestr.c -- routines for managing the global cube structure -*/ - -#include "espresso.h" - -/* - cube_setup -- assume that the fields "num_vars", "num_binary_vars", and - part_size[num_binary_vars .. num_vars-1] are setup, and initialize the - rest of cube and cdata. - - If a part_size is < 0, then the field size is abs(part_size) and the - field read from the input is symbolic. -*/ -void cube_setup() -{ - register int i, var; - register pcube p; - - if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars) - fatal("cube size is silly, error in .i/.o or .mv"); - - cube.num_mv_vars = cube.num_vars - cube.num_binary_vars; - cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1; - - cube.size = 0; - cube.first_part = ALLOC(int, cube.num_vars); - cube.last_part = ALLOC(int, cube.num_vars); - cube.first_word = ALLOC(int, cube.num_vars); - cube.last_word = ALLOC(int, cube.num_vars); - for(var = 0; var < cube.num_vars; var++) { - if (var < cube.num_binary_vars) - cube.part_size[var] = 2; - cube.first_part[var] = cube.size; - cube.first_word[var] = WHICH_WORD(cube.size); - cube.size += ABS(cube.part_size[var]); - cube.last_part[var] = cube.size - 1; - cube.last_word[var] = WHICH_WORD(cube.size - 1); - } - - cube.var_mask = ALLOC(pset, cube.num_vars); - cube.sparse = ALLOC(int, cube.num_vars); - cube.binary_mask = new_cube(); - cube.mv_mask = new_cube(); - for(var = 0; var < cube.num_vars; var++) { - p = cube.var_mask[var] = new_cube(); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - set_insert(p, i); - if (var < cube.num_binary_vars) { - INLINEset_or(cube.binary_mask, cube.binary_mask, p); - cube.sparse[var] = 0; - } else { - INLINEset_or(cube.mv_mask, cube.mv_mask, p); - cube.sparse[var] = 1; - } - } - if (cube.num_binary_vars == 0) - cube.inword = -1; - else { - cube.inword = cube.last_word[cube.num_binary_vars - 1]; - cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; - } - - cube.temp = ALLOC(pset, CUBE_TEMP); - for(i = 0; i < CUBE_TEMP; i++) - cube.temp[i] = new_cube(); - cube.fullset = set_fill(new_cube(), cube.size); - cube.emptyset = new_cube(); - - cdata.part_zeros = ALLOC(int, cube.size); - cdata.var_zeros = ALLOC(int, cube.num_vars); - cdata.parts_active = ALLOC(int, cube.num_vars); - cdata.is_unate = ALLOC(int, cube.num_vars); -} - -/* - setdown_cube -- free memory allocated for the cube/cdata structs - (free's all but the part_size array) - - (I wanted to call this cube_setdown, but that violates the 8-character - external routine limit on the IBM !) -*/ -void setdown_cube() -{ - register int i, var; - - FREE(cube.first_part); - FREE(cube.last_part); - FREE(cube.first_word); - FREE(cube.last_word); - FREE(cube.sparse); - - free_cube(cube.binary_mask); - free_cube(cube.mv_mask); - free_cube(cube.fullset); - free_cube(cube.emptyset); - for(var = 0; var < cube.num_vars; var++) - free_cube(cube.var_mask[var]); - FREE(cube.var_mask); - - for(i = 0; i < CUBE_TEMP; i++) - free_cube(cube.temp[i]); - FREE(cube.temp); - - FREE(cdata.part_zeros); - FREE(cdata.var_zeros); - FREE(cdata.parts_active); - FREE(cdata.is_unate); - - cube.first_part = cube.last_part = (int *) NULL; - cube.first_word = cube.last_word = (int *) NULL; - cube.sparse = (int *) NULL; - cube.binary_mask = cube.mv_mask = (pcube) NULL; - cube.fullset = cube.emptyset = (pcube) NULL; - cube.var_mask = cube.temp = (pcube *) NULL; - - cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; - cdata.is_unate = (bool *) NULL; -} - - -void save_cube_struct() -{ - temp_cube_save = cube; /* structure copy ! */ - temp_cdata_save = cdata; /* "" */ - - cube.first_part = cube.last_part = (int *) NULL; - cube.first_word = cube.last_word = (int *) NULL; - cube.part_size = (int *) NULL; - cube.binary_mask = cube.mv_mask = (pcube) NULL; - cube.fullset = cube.emptyset = (pcube) NULL; - cube.var_mask = cube.temp = (pcube *) NULL; - - cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; - cdata.is_unate = (bool *) NULL; -} - - -void restore_cube_struct() -{ - cube = temp_cube_save; /* structure copy ! */ - cdata = temp_cdata_save; /* "" */ -} diff --git a/src/benchmarks/espresso/cvrin.c b/src/benchmarks/espresso/cvrin.c deleted file mode 100644 index d3388fb..0000000 --- a/src/benchmarks/espresso/cvrin.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - module: cvrin.c - purpose: cube and cover input routines -*/ - -#include "espresso.h" - -static bool line_length_error; -static int lineno; - -void skip_line(fpin, fpout, echo) -register FILE *fpin, *fpout; -register bool echo; -{ - register int ch; - while ((ch=getc(fpin)) != EOF && ch != '\n') - if (echo) - putc(ch, fpout); - if (echo) - putc('\n', fpout); - lineno++; -} - -char *get_word(fp, word) -register FILE *fp; -register char *word; -{ - register int ch, i = 0; - while ((ch = getc(fp)) != EOF && isspace(ch)) - ; - word[i++] = ch; - while ((ch = getc(fp)) != EOF && ! isspace(ch)) - word[i++] = ch; - word[i++] = '\0'; - return word; -} - -/* - * Yes, I know this routine is a mess - */ -void read_cube(fp, PLA) -register FILE *fp; -pPLA PLA; -{ - register int var, i; - pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2]; - bool savef = FALSE, saved = FALSE, saver = FALSE; - char token[256]; /* for kiss read hack */ - int varx, first, last, offset; /* for kiss read hack */ - - set_clear(cf, cube.size); - - /* Loop and read binary variables */ - for(var = 0; var < cube.num_binary_vars; var++) - switch(getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - var--; - break; - case ' ': case '|': case '\t': - var--; - break; - case '2': case '-': - set_insert(cf, var*2+1); - case '0': - set_insert(cf, var*2); - break; - case '1': - set_insert(cf, var*2+1); - break; - case '?': - break; - default: - goto bad_char; - } - - - /* Loop for the all but one of the multiple-valued variables */ - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) - - /* Read a symbolic multiple-valued variable */ - if (cube.part_size[var] < 0) { - (void) fscanf(fp, "%s", token); - if (equal(token, "-") || equal(token, "ANY")) { - if (kiss && var == cube.num_vars - 2) { - /* leave it empty */ - } else { - /* make it full */ - set_or(cf, cf, cube.var_mask[var]); - } - } else if (equal(token, "~")) { - ; - /* leave it empty ... (?) */ - } else { - if (kiss && var == cube.num_vars - 2) - varx = var - 1, offset = ABS(cube.part_size[var-1]); - else - varx = var, offset = 0; - /* Find the symbolic label in the label table */ - first = cube.first_part[varx]; - last = cube.last_part[varx]; - for(i = first; i <= last; i++) - if (PLA->label[i] == (char *) NULL) { - PLA->label[i] = util_strsav(token); /* add new label */ - set_insert(cf, i+offset); - break; - } else if (equal(PLA->label[i], token)) { - set_insert(cf, i+offset); /* use column i */ - break; - } - if (i > last) { - fprintf(stderr, -"declared size of variable %d (counting from variable 0) is too small\n", var); - exit(-1); - } - } - - } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - switch (getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - i--; - break; - case ' ': case '|': case '\t': - i--; - break; - case '1': - set_insert(cf, i); - case '0': - break; - default: - goto bad_char; - } - - /* Loop for last multiple-valued variable */ - if (kiss) { - saver = savef = TRUE; - (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]); - } else - set_copy(cr, cf); - set_copy(cd, cf); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - switch (getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - i--; - break; - case ' ': case '|': case '\t': - i--; - break; - case '4': case '1': - if (PLA->pla_type & F_type) - set_insert(cf, i), savef = TRUE; - break; - case '3': case '0': - if (PLA->pla_type & R_type) - set_insert(cr, i), saver = TRUE; - break; - case '2': case '-': - if (PLA->pla_type & D_type) - set_insert(cd, i), saved = TRUE; - case '~': - break; - default: - goto bad_char; - } - if (savef) PLA->F = sf_addset(PLA->F, cf); - if (saved) PLA->D = sf_addset(PLA->D, cd); - if (saver) PLA->R = sf_addset(PLA->R, cr); - return; - -bad_char: - fprintf(stderr, "(warning): input line #%d ignored\n", lineno); - skip_line(fp, stdout, TRUE); - return; -} -void parse_pla(fp, PLA) -IN FILE *fp; -INOUT pPLA PLA; -{ - int i, var, ch, np, last; - char word[256]; - - lineno = 1; - line_length_error = FALSE; - -loop: - switch(ch = getc(fp)) { - case EOF: - return; - - case '\n': - lineno++; - - case ' ': case '\t': case '\f': case '\r': - break; - - case '#': - (void) ungetc(ch, fp); - skip_line(fp, stdout, echo_comments); - break; - - case '.': - /* .i gives the cube input size (binary-functions only) */ - if (equal(get_word(fp, word), "i")) { - if (cube.fullset != NULL) { - fprintf(stderr, "extra .i ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (fscanf(fp, "%d", &cube.num_binary_vars) != 1) - fatal("error reading .i"); - cube.num_vars = cube.num_binary_vars + 1; - cube.part_size = ALLOC(int, cube.num_vars); - } - - /* .o gives the cube output size (binary-functions only) */ - } else if (equal(word, "o")) { - if (cube.fullset != NULL) { - fprintf(stderr, "extra .o ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (cube.part_size == NULL) - fatal(".o cannot appear before .i"); - if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1) - fatal("error reading .o"); - cube_setup(); - PLA_labels(PLA); - } - - /* .mv gives the cube size for a multiple-valued function */ - } else if (equal(word, "mv")) { - if (cube.fullset != NULL) { - fprintf(stderr, "extra .mv ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (cube.part_size != NULL) - fatal("cannot mix .i and .mv"); - if (fscanf(fp,"%d %d", - &cube.num_vars,&cube.num_binary_vars) != 2) - fatal("error reading .mv"); - if (cube.num_binary_vars < 0) -fatal("num_binary_vars (second field of .mv) cannot be negative"); - if (cube.num_vars < cube.num_binary_vars) - fatal( -"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)"); - cube.part_size = ALLOC(int, cube.num_vars); - for(var=cube.num_binary_vars; var < cube.num_vars; var++) - if (fscanf(fp, "%d", &(cube.part_size[var])) != 1) - fatal("error reading .mv"); - cube_setup(); - PLA_labels(PLA); - } - - /* .p gives the number of product terms -- we ignore it */ - } else if (equal(word, "p")) - (void) fscanf(fp, "%d", &np); - /* .e and .end specify the end of the file */ - else if (equal(word, "e") || equal(word,"end")) - return; - /* .kiss turns on the kiss-hack option */ - else if (equal(word, "kiss")) - kiss = TRUE; - - /* .type specifies a logical type for the PLA */ - else if (equal(word, "type")) { - (void) get_word(fp, word); - for(i = 0; pla_types[i].key != 0; i++) - if (equal(pla_types[i].key + 1, word)) { - PLA->pla_type = pla_types[i].value; - break; - } - if (pla_types[i].key == 0) - fatal("unknown type in .type command"); - - /* parse the labels */ - } else if (equal(word, "ilb")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .ilb or .ob"); - if (PLA->label == NULL) - PLA_labels(PLA); - for(var = 0; var < cube.num_binary_vars; var++) { - (void) get_word(fp, word); - i = cube.first_part[var]; - PLA->label[i+1] = util_strsav(word); - PLA->label[i] = ALLOC(char, strlen(word) + 6); - (void) sprintf(PLA->label[i], "%s.bar", word); - } - } else if (equal(word, "ob")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .ilb or .ob"); - if (PLA->label == NULL) - PLA_labels(PLA); - var = cube.num_vars - 1; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - (void) get_word(fp, word); - PLA->label[i] = util_strsav(word); - } - /* .label assigns labels to multiple-valued variables */ - } else if (equal(word, "label")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .label"); - if (PLA->label == NULL) - PLA_labels(PLA); - if (fscanf(fp, "var=%d", &var) != 1) - fatal("Error reading labels"); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - (void) get_word(fp, word); - PLA->label[i] = util_strsav(word); - } - - } else if (equal(word, "symbolic")) { - symbolic_t *newlist, *p1; - if (read_symbolic(fp, PLA, word, &newlist)) { - if (PLA->symbolic == NIL(symbolic_t)) { - PLA->symbolic = newlist; - } else { - for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t); - p1=p1->next){ - } - p1->next = newlist; - } - } else { - fatal("error reading .symbolic"); - } - - } else if (equal(word, "symbolic-output")) { - symbolic_t *newlist, *p1; - if (read_symbolic(fp, PLA, word, &newlist)) { - if (PLA->symbolic_output == NIL(symbolic_t)) { - PLA->symbolic_output = newlist; - } else { - for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t); - p1=p1->next){ - } - p1->next = newlist; - } - } else { - fatal("error reading .symbolic-output"); - } - - /* .phase allows a choice of output phases */ - } else if (equal(word, "phase")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .phase"); - if (PLA->phase != NULL) { - fprintf(stderr, "extra .phase ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - do ch = getc(fp); while (ch == ' ' || ch == '\t'); - (void) ungetc(ch, fp); - PLA->phase = set_save(cube.fullset); - last = cube.last_part[cube.num_vars - 1]; - for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++) - if ((ch = getc(fp)) == '0') - set_remove(PLA->phase, i); - else if (ch != '1') - fatal("only 0 or 1 allowed in phase description"); - } - - /* .pair allows for bit-pairing input variables */ - } else if (equal(word, "pair")) { - int j; - if (PLA->pair != NULL) { - fprintf(stderr, "extra .pair ignored\n"); - } else { - ppair pair; - PLA->pair = pair = ALLOC(pair_t, 1); - if (fscanf(fp, "%d", &(pair->cnt)) != 1) - fatal("syntax error in .pair"); - pair->var1 = ALLOC(int, pair->cnt); - pair->var2 = ALLOC(int, pair->cnt); - for(i = 0; i < pair->cnt; i++) { - (void) get_word(fp, word); - if (word[0] == '(') (void) strcpy(word, word+1); - if (label_index(PLA, word, &var, &j)) { - pair->var1[i] = var+1; - } else { - fatal("syntax error in .pair"); - } - - (void) get_word(fp, word); - if (word[strlen(word)-1] == ')') { - word[strlen(word)-1]='\0'; - } - if (label_index(PLA, word, &var, &j)) { - pair->var2[i] = var+1; - } else { - fatal("syntax error in .pair"); - } - } - } - - } else { - if (echo_unknown_commands) - printf("%c%s ", ch, word); - skip_line(fp, stdout, echo_unknown_commands); - } - break; - default: - (void) ungetc(ch, fp); - if (cube.fullset == NULL) { -/* fatal("unknown PLA size, need .i/.o or .mv");*/ - if (echo_comments) - putchar('#'); - skip_line(fp, stdout, echo_comments); - break; - } - if (PLA->F == NULL) { - PLA->F = new_cover(10); - PLA->D = new_cover(10); - PLA->R = new_cover(10); - } - read_cube(fp, PLA); - } - goto loop; -} -/* - read_pla -- read a PLA from a file - - Input stops when ".e" is encountered in the input file, or upon reaching - end of file. - - Returns the PLA in the variable PLA after massaging the "symbolic" - representation into a positional cube notation of the ON-set, OFF-set, - and the DC-set. - - needs_dcset and needs_offset control the computation of the OFF-set - and DC-set (i.e., if either needs to be computed, then it will be - computed via complement only if the corresponding option is TRUE.) - pla_type specifies the interpretation to be used when reading the - PLA. - - The phase of the output functions is adjusted according to the - global option "pos" or according to an imbedded .phase option in - the input file. Note that either phase option implies that the - OFF-set be computed regardless of whether the caller needs it - explicitly or not. - - Bit pairing of the binary variables is performed according to an - imbedded .pair option in the input file. - - The global cube structure also reflects the sizes of the PLA which - was just read. If these fields have already been set, then any - subsequent PLA must conform to these sizes. - - The global flags trace and summary control the output produced - during the read. - - Returns a status code as a result: - EOF (-1) : End of file reached before any data was read - > 0 : Operation successful -*/ - -int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return) -IN FILE *fp; -IN bool needs_dcset, needs_offset; -IN int pla_type; -OUT pPLA *PLA_return; -{ - pPLA PLA; - int i, second, third; - long time; - cost_t cost; - - /* Allocate and initialize the PLA structure */ - PLA = *PLA_return = new_PLA(); - PLA->pla_type = pla_type; - - /* Read the pla */ - time = ptime(); - parse_pla(fp, PLA); - - /* Check for nothing on the file -- implies reached EOF */ - if (PLA->F == NULL) { - return EOF; - } - - /* This hack merges the next-state field with the outputs */ - for(i = 0; i < cube.num_vars; i++) { - cube.part_size[i] = ABS(cube.part_size[i]); - } - if (kiss) { - third = cube.num_vars - 3; - second = cube.num_vars - 2; - if (cube.part_size[third] != cube.part_size[second]) { - fprintf(stderr," with .kiss option, third to last and second\n"); - fprintf(stderr, "to last variables must be the same size.\n"); - return EOF; - } - for(i = 0; i < cube.part_size[second]; i++) { - PLA->label[i + cube.first_part[second]] = - util_strsav(PLA->label[i + cube.first_part[third]]); - } - cube.part_size[second] += cube.part_size[cube.num_vars-1]; - cube.num_vars--; - setdown_cube(); - cube_setup(); - } - - if (trace) { - totals(time, READ_TIME, PLA->F, &cost); - } - - /* Decide how to break PLA into ON-set, OFF-set and DC-set */ - time = ptime(); - if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) { - needs_offset = TRUE; - } - if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) { - free_cover(PLA->R); - PLA->R = complement(cube2list(PLA->F, PLA->D)); - } else if (needs_dcset && PLA->pla_type == FR_type) { - pcover X; - free_cover(PLA->D); - /* hack, why not? */ - X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1); - PLA->D = complement(cube1list(X)); - free_cover(X); - } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) { - free_cover(PLA->F); - PLA->F = complement(cube2list(PLA->D, PLA->R)); - } - - if (trace) { - totals(time, COMPL_TIME, PLA->R, &cost); - } - - /* Check for phase rearrangement of the functions */ - if (pos) { - pcover onset = PLA->F; - PLA->F = PLA->R; - PLA->R = onset; - PLA->phase = new_cube(); - set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]); - } else if (PLA->phase != NULL) { - (void) set_phase(PLA); - } - - /* Setup minimization for two-bit decoders */ - if (PLA->pair != (ppair) NULL) { - set_pair(PLA); - } - - if (PLA->symbolic != NIL(symbolic_t)) { - EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F); - } - if (PLA->symbolic_output != NIL(symbolic_t)) { - EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F); - if (needs_offset) { - free_cover(PLA->R); -EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost); - } - } - - return 1; -} - -void PLA_summary(PLA) -pPLA PLA; -{ - int var, i; - symbolic_list_t *p2; - symbolic_t *p1; - - printf("# PLA is %s", PLA->filename); - if (cube.num_binary_vars == cube.num_vars - 1) - printf(" with %d inputs and %d outputs\n", - cube.num_binary_vars, cube.part_size[cube.num_vars - 1]); - else { - printf(" with %d variables (%d binary, mv sizes", - cube.num_vars, cube.num_binary_vars); - for(var = cube.num_binary_vars; var < cube.num_vars; var++) - printf(" %d", cube.part_size[var]); - printf(")\n"); - } - printf("# ON-set cost is %s\n", print_cost(PLA->F)); - printf("# OFF-set cost is %s\n", print_cost(PLA->R)); - printf("# DC-set cost is %s\n", print_cost(PLA->D)); - if (PLA->phase != NULL) - printf("# phase is %s\n", pc1(PLA->phase)); - if (PLA->pair != NULL) { - printf("# two-bit decoders:"); - for(i = 0; i < PLA->pair->cnt; i++) - printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]); - printf("\n"); - } - if (PLA->symbolic != NIL(symbolic_t)) { - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - printf("# symbolic: "); - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - printf(" %d", p2->variable); - } - printf("\n"); - } - } - if (PLA->symbolic_output != NIL(symbolic_t)) { - for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) { - printf("# output symbolic: "); - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - printf(" %d", p2->pos); - } - printf("\n"); - } - } - (void) fflush(stdout); -} - - -pPLA new_PLA() -{ - pPLA PLA; - - PLA = ALLOC(PLA_t, 1); - PLA->F = PLA->D = PLA->R = (pcover) NULL; - PLA->phase = (pcube) NULL; - PLA->pair = (ppair) NULL; - PLA->label = (char **) NULL; - PLA->filename = (char *) NULL; - PLA->pla_type = 0; - PLA->symbolic = NIL(symbolic_t); - PLA->symbolic_output = NIL(symbolic_t); - return PLA; -} - - -PLA_labels(PLA) -pPLA PLA; -{ - int i; - - PLA->label = ALLOC(char *, cube.size); - for(i = 0; i < cube.size; i++) - PLA->label[i] = (char *) NULL; -} - - -void free_PLA(PLA) -pPLA PLA; -{ - symbolic_list_t *p2, *p2next; - symbolic_t *p1, *p1next; - int i; - - if (PLA->F != (pcover) NULL) - free_cover(PLA->F); - if (PLA->R != (pcover) NULL) - free_cover(PLA->R); - if (PLA->D != (pcover) NULL) - free_cover(PLA->D); - if (PLA->phase != (pcube) NULL) - free_cube(PLA->phase); - if (PLA->pair != (ppair) NULL) { - FREE(PLA->pair->var1); - FREE(PLA->pair->var2); - FREE(PLA->pair); - } - if (PLA->label != NULL) { - for(i = 0; i < cube.size; i++) - if (PLA->label[i] != NULL) - FREE(PLA->label[i]); - FREE(PLA->label); - } - if (PLA->filename != NULL) { - FREE(PLA->filename); - } - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) { - for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { - p2next = p2->next; - FREE(p2); - } - p1next = p1->next; - FREE(p1); - } - PLA->symbolic = NIL(symbolic_t); - for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) { - for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { - p2next = p2->next; - FREE(p2); - } - p1next = p1->next; - FREE(p1); - } - PLA->symbolic_output = NIL(symbolic_t); - FREE(PLA); -} - - -int read_symbolic(fp, PLA, word, retval) -FILE *fp; -pPLA PLA; -char *word; /* scratch string for words */ -symbolic_t **retval; -{ - symbolic_list_t *listp, *prev_listp; - symbolic_label_t *labelp, *prev_labelp; - symbolic_t *newlist; - int i, var; - - newlist = ALLOC(symbolic_t, 1); - newlist->next = NIL(symbolic_t); - newlist->symbolic_list = NIL(symbolic_list_t); - newlist->symbolic_list_length = 0; - newlist->symbolic_label = NIL(symbolic_label_t); - newlist->symbolic_label_length = 0; - prev_listp = NIL(symbolic_list_t); - prev_labelp = NIL(symbolic_label_t); - - for(;;) { - (void) get_word(fp, word); - if (equal(word, ";")) - break; - if (label_index(PLA, word, &var, &i)) { - listp = ALLOC(symbolic_list_t, 1); - listp->variable = var; - listp->pos = i; - listp->next = NIL(symbolic_list_t); - if (prev_listp == NIL(symbolic_list_t)) { - newlist->symbolic_list = listp; - } else { - prev_listp->next = listp; - } - prev_listp = listp; - newlist->symbolic_list_length++; - } else { - return FALSE; - } - } - - for(;;) { - (void) get_word(fp, word); - if (equal(word, ";")) - break; - labelp = ALLOC(symbolic_label_t, 1); - labelp->label = util_strsav(word); - labelp->next = NIL(symbolic_label_t); - if (prev_labelp == NIL(symbolic_label_t)) { - newlist->symbolic_label = labelp; - } else { - prev_labelp->next = labelp; - } - prev_labelp = labelp; - newlist->symbolic_label_length++; - } - - *retval = newlist; - return TRUE; -} - - -int label_index(PLA, word, varp, ip) -pPLA PLA; -char *word; -int *varp; -int *ip; -{ - int var, i; - - if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) { - if (sscanf(word, "%d", varp) == 1) { - *ip = *varp; - return TRUE; - } - } else { - for(var = 0; var < cube.num_vars; var++) { - for(i = 0; i < cube.part_size[var]; i++) { - if (equal(PLA->label[cube.first_part[var]+i], word)) { - *varp = var; - *ip = i; - return TRUE; - } - } - } - } - return FALSE; -} diff --git a/src/benchmarks/espresso/cvrm.c b/src/benchmarks/espresso/cvrm.c deleted file mode 100644 index 1fb21e2..0000000 --- a/src/benchmarks/espresso/cvrm.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - module: cvrm.c - Purpose: miscellaneous cover manipulation - a) verify two covers are equal, check consistency of a cover - b) unravel a multiple-valued cover into minterms - c) sort covers -*/ - -#include "espresso.h" - - -static void cb_unravel(c, start, end, startbase, B1) -IN register pcube c; -IN int start, end; -IN pcube startbase; -INOUT pcover B1; -{ - pcube base = cube.temp[0], p, last; - int expansion, place, skip, var, size, offset; - register int i, j, k, n; - - /* Determine how many cubes it will blow up into, and create a mask - for those parts that have only a single coordinate - */ - expansion = 1; - (void) set_copy(base, startbase); - for(var = start; var <= end; var++) { - if ((size = set_dist(c, cube.var_mask[var])) < 2) { - (void) set_or(base, base, cube.var_mask[var]); - } else { - expansion *= size; - } - } - (void) set_and(base, c, base); - - /* Add the unravelled sets starting at the last element of B1 */ - offset = B1->count; - B1->count += expansion; - foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) { - INLINEset_copy(p, base); - } - - place = expansion; - for(var = start; var <= end; var++) { - if ((size = set_dist(c, cube.var_mask[var])) > 1) { - skip = place; - place = place / size; - n = 0; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (is_in_set(c, i)) { - for(j = n; j < expansion; j += skip) { - for(k = 0; k < place; k++) { - p = GETSET(B1, j+k+offset); - (void) set_insert(p, i); - } - } - n += place; - } - } - } - } -} - - -pcover unravel_range(B, start, end) -IN pcover B; -IN int start, end; -{ - pcover B1; - int var, total_size, expansion, size; - register pcube p, last, startbase = cube.temp[1]; - - /* Create the starting base for those variables not being unravelled */ - (void) set_copy(startbase, cube.emptyset); - for(var = 0; var < start; var++) - (void) set_or(startbase, startbase, cube.var_mask[var]); - for(var = end+1; var < cube.num_vars; var++) - (void) set_or(startbase, startbase, cube.var_mask[var]); - - /* Determine how many cubes it will blow up into */ - total_size = 0; - foreach_set(B, last, p) { - expansion = 1; - for(var = start; var <= end; var++) - if ((size = set_dist(p, cube.var_mask[var])) >= 2) - if ((expansion *= size) > 1000000) - fatal("unreasonable expansion in unravel"); - total_size += expansion; - } - - /* We can now allocate a cover of exactly the correct size */ - B1 = new_cover(total_size); - foreach_set(B, last, p) { - cb_unravel(p, start, end, startbase, B1); - } - free_cover(B); - return B1; -} - - -pcover unravel(B, start) -IN pcover B; -IN int start; -{ - return unravel_range(B, start, cube.num_vars-1); -} - -/* lex_sort -- sort cubes in a standard lexical fashion */ -pcover lex_sort(T) -pcover T; -{ - pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size); - free_cover(T); - return T1; -} - - -/* size_sort -- sort cubes by their size */ -pcover size_sort(T) -pcover T; -{ - pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size); - free_cover(T); - return T1; -} - - -/* mini_sort -- sort cubes according to the heuristics of mini */ -pcover mini_sort(F, compare) -pcover F; -int (*compare)(); -{ - register int *count, cnt, n = cube.size, i; - register pcube p, last; - pcover F_sorted; - pcube *F1; - - /* Perform a column sum over the set family */ - count = sf_count(F); - - /* weight is "inner product of the cube and the column sums" */ - foreach_set(F, last, p) { - cnt = 0; - for(i = 0; i < n; i++) - if (is_in_set(p, i)) - cnt += count[i]; - PUTSIZE(p, cnt); - } - FREE(count); - - /* use qsort to sort the array */ - qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare); - F_sorted = sf_unlist(F1, F->count, F->sf_size); - free_cover(F); - - return F_sorted; -} - - -/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */ -pcover sort_reduce(T) -IN pcover T; -{ - register pcube p, last, largest = NULL; - register int bestsize = -1, size, n = cube.num_vars; - pcover T_sorted; - pcube *T1; - - if (T->count == 0) - return T; - - /* find largest cube */ - foreach_set(T, last, p) - if ((size = set_ord(p)) > bestsize) - largest = p, bestsize = size; - - foreach_set(T, last, p) - PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127)); - - qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), descend); - T_sorted = sf_unlist(T1, T->count, T->sf_size); - free_cover(T); - - return T_sorted; -} - -pcover random_order(F) -register pcover F; -{ - pset temp; - register int i, k; -#ifdef RANDOM - long random(); -#endif - - temp = set_new(F->sf_size); - for(i = F->count - 1; i > 0; i--) { - /* Choose a random number between 0 and i */ -#ifdef RANDOM - k = random() % i; -#else - /* this is not meant to be really used; just provides an easy - "out" if random() and srandom() aren't around - */ - k = (i*23 + 997) % i; -#endif - /* swap sets i and k */ - set_copy(temp, GETSET(F, k)); - set_copy(GETSET(F, k), GETSET(F, i)); - set_copy(GETSET(F, i), temp); - } - set_free(temp); - return F; -} - -/* - * cubelist_partition -- take a cubelist T and see if it has any components; - * if so, return cubelist's of the two partitions A and B; the return value - * is the size of the partition; if not, A and B - * are undefined and the return value is 0 - */ -int cubelist_partition(T, A, B, comp_debug) -pcube *T; /* a list of cubes */ -pcube **A, **B; /* cubelist of partition and remainder */ -unsigned int comp_debug; -{ - register pcube *T1, p, seed, cof; - pcube *A1, *B1; - bool change; - int count, numcube; - - numcube = CUBELISTSIZE(T); - - /* Mark all cubes -- covered cubes belong to the partition */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - RESET(p, COVERED); - } - - /* - * Extract a partition from the cubelist T; start with the first cube as a - * seed, and then pull in all cubes which share a variable with the seed; - * iterate until no new cubes are brought into the partition. - */ - seed = set_save(T[2]); - cof = T[0]; - SET(T[2], COVERED); - count = 1; - - do { - change = FALSE; - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) { - INLINEset_and(seed, seed, p); - SET(p, COVERED); - change = TRUE; - count++; - } - - } - } while (change); - - set_free(seed); - - if (comp_debug) { - printf("COMPONENT_REDUCTION: split into %d %d\n", - count, numcube - count); - } - - if (count != numcube) { - /* Allocate and setup the cubelist's for the two partitions */ - *A = A1 = ALLOC(pcube, numcube+3); - *B = B1 = ALLOC(pcube, numcube+3); - (*A)[0] = set_save(T[0]); - (*B)[0] = set_save(T[0]); - A1 = *A + 2; - B1 = *B + 2; - - /* Loop over the cubes in T and distribute to A and B */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (TESTP(p, COVERED)) { - *A1++ = p; - } else { - *B1++ = p; - } - } - - /* Stuff needed at the end of the cubelist's */ - *A1++ = NULL; - (*A)[1] = (pcube) A1; - *B1++ = NULL; - (*B)[1] = (pcube) B1; - } - - return numcube - count; -} - -/* - * quick cofactor against a single output function - */ -pcover cof_output(T, i) -pcover T; -register int i; -{ - pcover T1; - register pcube p, last, pdest, mask; - - mask = cube.var_mask[cube.output]; - T1 = new_cover(T->count); - foreach_set(T, last, p) { - if (is_in_set(p, i)) { - pdest = GETSET(T1, T1->count++); - INLINEset_or(pdest, p, mask); - RESET(pdest, PRIME); - } - } - return T1; -} - - -/* - * quick intersection against a single output function - */ -pcover uncof_output(T, i) -pcover T; -int i; -{ - register pcube p, last, mask; - - if (T == NULL) { - return T; - } - - mask = cube.var_mask[cube.output]; - foreach_set(T, last, p) { - INLINEset_diff(p, p, mask); - set_insert(p, i); - } - return T; -} - - -/* - * A generic routine to perform an operation for each output function - * - * func() is called with a PLA for each output function (with the output - * part effectively removed). - * func1() is called after reforming the equivalent output function - * - * Each function returns TRUE if process is to continue - */ -foreach_output_function(PLA, func, func1) -pPLA PLA; -int (*func)(); -int (*func1)(); -{ - pPLA PLA1; - int i; - - /* Loop for each output function */ - for(i = 0; i < cube.part_size[cube.output]; i++) { - - /* cofactor on the output part */ - PLA1 = new_PLA(); - PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]); - PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]); - PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]); - - /* Call a routine to do something with the cover */ - if ((*func)(PLA1, i) == 0) { - free_PLA(PLA1); - return 0; - } - - /* intersect with the particular output part again */ - PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]); - PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]); - PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]); - - /* Call a routine to do something with the final result */ - if ((*func1)(PLA1, i) == 0) { - free_PLA(PLA1); - return 0; - } - - /* Cleanup for next go-around */ - free_PLA(PLA1); - - } - return 0; -} - -static pcover Fmin; -static pcube phase; - -/* - * minimize each output function individually - */ -void so_espresso(PLA, strategy) -pPLA PLA; -int strategy; -{ - Fmin = new_cover(PLA->F->count); - if (strategy == 0) { - foreach_output_function(PLA, so_do_espresso, so_save); - } else { - foreach_output_function(PLA, so_do_exact, so_save); - } - sf_free(PLA->F); - PLA->F = Fmin; -} - - -/* - * minimize each output function, choose function or complement based on the - * one with the fewer number of terms - */ -void so_both_espresso(PLA, strategy) -pPLA PLA; -int strategy; -{ - phase = set_save(cube.fullset); - Fmin = new_cover(PLA->F->count); - if (strategy == 0) { - foreach_output_function(PLA, so_both_do_espresso, so_both_save); - } else { - foreach_output_function(PLA, so_both_do_exact, so_both_save); - } - sf_free(PLA->F); - PLA->F = Fmin; - PLA->phase = phase; -} - - -int so_do_espresso(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - skip_make_sparse = 1; - (void) sprintf(word, "ESPRESSO-POS(%d)", i); - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); - return 1; -} - - -int so_do_exact(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - skip_make_sparse = 1; - (void) sprintf(word, "EXACT-POS(%d)", i); - EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); - return 1; -} - - -/*ARGSUSED*/ -int so_save(PLA, i) -pPLA PLA; -int i; -{ - Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */ - PLA->F = NULL; - return 1; -} - - -int so_both_do_espresso(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - (void) sprintf(word, "ESPRESSO-POS(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); - - /* minimize the single-output function (off-set) */ - (void) sprintf(word, "ESPRESSO-NEG(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R); - - return 1; -} - - -int so_both_do_exact(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - (void) sprintf(word, "EXACT-POS(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); - - /* minimize the single-output function (off-set) */ - (void) sprintf(word, "EXACT-NEG(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R); - - return 1; -} - - -int so_both_save(PLA, i) -pPLA PLA; -int i; -{ - if (PLA->F->count > PLA->R->count) { - sf_free(PLA->F); - PLA->F = PLA->R; - PLA->R = NULL; - i += cube.first_part[cube.output]; - set_remove(phase, i); - } else { - sf_free(PLA->R); - PLA->R = NULL; - } - Fmin = sf_append(Fmin, PLA->F); - PLA->F = NULL; - return 1; -} diff --git a/src/benchmarks/espresso/cvrmisc.c b/src/benchmarks/espresso/cvrmisc.c deleted file mode 100644 index f0be0c3..0000000 --- a/src/benchmarks/espresso/cvrmisc.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "espresso.h" - - -/* cost -- compute the cost of a cover */ -void cover_cost(F, cost) -IN pcover F; -INOUT pcost cost; -{ - register pcube p, last; - pcube *T; - int var; - - /* use the routine used by cofactor to decide splitting variables */ - massive_count(T = cube1list(F)); - free_cubelist(T); - - cost->cubes = F->count; - cost->total = cost->in = cost->out = cost->mv = cost->primes = 0; - - /* Count transistors (zeros) for each binary variable (inputs) */ - for(var = 0; var < cube.num_binary_vars; var++) - cost->in += cdata.var_zeros[var]; - - /* Count transistors for each mv variable based on sparse/dense */ - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) - if (cube.sparse[var]) - cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var]; - else - cost->mv += cdata.var_zeros[var]; - - /* Count the transistors (ones) for the output variable */ - if (cube.num_binary_vars != cube.num_vars) { - var = cube.num_vars - 1; - cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var]; - } - - /* Count the number of nonprime cubes */ - /* - THIS IS A BUG! p is never set! EDB... - - foreach_set(F, last, p) - cost->primes += TESTP(p, PRIME) != 0; - */ - - /* Count the total number of literals */ - cost->total = cost->in + cost->out + cost->mv; -} - - -/* fmt_cost -- return a string which reports the "cost" of a cover */ -char *fmt_cost(cost) -IN pcost cost; -{ - static char s[200]; - - if (cube.num_binary_vars == cube.num_vars - 1) { - int v1 = cost->primes + 1; - sprintf (s, "%d", v1); - (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d", - cost->cubes, cost->cubes - cost->primes, cost->in, - cost->out, cost->total); - } else { - (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d", - cost->cubes, cost->cubes - cost->primes, cost->in, - cost->mv, cost->out); - } - return s; -} - - -char *print_cost(F) -IN pcover F; -{ - cost_t cost; - cover_cost(F, &cost); - return fmt_cost(&cost); -} - - -/* copy_cost -- copy a cost function from s to d */ -void copy_cost(s, d) -pcost s, d; -{ - d->cubes = s->cubes; - d->in = s->in; - d->out = s->out; - d->mv = s->mv; - d->total = s->total; - d->primes = s->primes; -} - - -/* size_stamp -- print single line giving the size of a cover */ -void size_stamp(T, name) -IN pcover T; -IN char *name; -{ - printf("# %s\tCost is %s\n", name, print_cost(T)); - (void) fflush(stdout); -} - - -/* print_trace -- print a line reporting size and time after a function */ -void print_trace(T, name, time) -pcover T; -char *name; -long time; -{ - printf("# %s\tTime was %s, cost is %s\n", - name, print_time(time), print_cost(T)); - (void) fflush(stdout); -} - - -/* totals -- add time spent in the function into the totals */ -void totals(time, i, T, cost) -long time; -int i; -pcover T; -pcost cost; -{ - time = ptime() - time; - total_time[i] += time; - total_calls[i]++; - cover_cost(T, cost); - if (trace) { - printf("# %s\tTime was %s, cost is %s\n", - total_name[i], print_time(time), fmt_cost(cost)); - (void) fflush(stdout); - } -} - - -/* fatal -- report fatal error message and take a dive */ -void fatal(s) -char *s; -{ - fprintf(stderr, "espresso: %s\n", s); - exit(1); -} diff --git a/src/benchmarks/espresso/cvrout.c b/src/benchmarks/espresso/cvrout.c deleted file mode 100644 index a8c7e67..0000000 --- a/src/benchmarks/espresso/cvrout.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - module: cvrout.c - purpose: cube and cover output routines -*/ - -#include "espresso.h" - -void fprint_pla(fp, PLA, output_type) -INOUT FILE *fp; -IN pPLA PLA; -IN int output_type; -{ - int num; - register pcube last, p; - - if ((output_type & CONSTRAINTS_type) != 0) { - output_symbolic_constraints(fp, PLA, 0); - output_type &= ~ CONSTRAINTS_type; - if (output_type == 0) { - return; - } - } - - if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) { - output_symbolic_constraints(fp, PLA, 1); - output_type &= ~ SYMBOLIC_CONSTRAINTS_type; - if (output_type == 0) { - return; - } - } - - if (output_type == PLEASURE_type) { - pls_output(PLA); - } else if (output_type == EQNTOTT_type) { - eqn_output(PLA); - } else if (output_type == KISS_type) { - kiss_output(fp, PLA); - } else { - fpr_header(fp, PLA, output_type); - - num = 0; - if (output_type & F_type) num += (PLA->F)->count; - if (output_type & D_type) num += (PLA->D)->count; - if (output_type & R_type) num += (PLA->R)->count; - fprintf(fp, ".p %d\n", num); - - /* quick patch 01/17/85 to support TPLA ! */ - if (output_type == F_type) { - foreach_set(PLA->F, last, p) { - print_cube(fp, p, "01"); - } - fprintf(fp, ".e\n"); - } else { - if (output_type & F_type) { - foreach_set(PLA->F, last, p) { - print_cube(fp, p, "~1"); - } - } - if (output_type & D_type) { - foreach_set(PLA->D, last, p) { - print_cube(fp, p, "~2"); - } - } - if (output_type & R_type) { - foreach_set(PLA->R, last, p) { - print_cube(fp, p, "~0"); - } - } - fprintf(fp, ".end\n"); - } - } -} - -void fpr_header(fp, PLA, output_type) -FILE *fp; -pPLA PLA; -int output_type; -{ - register int i, var; - int first, last; - - /* .type keyword gives logical type */ - if (output_type != F_type) { - fprintf(fp, ".type "); - if (output_type & F_type) putc('f', fp); - if (output_type & D_type) putc('d', fp); - if (output_type & R_type) putc('r', fp); - putc('\n', fp); - } - - /* Check for binary or multiple-valued labels */ - if (cube.num_mv_vars <= 1) { - fprintf(fp, ".i %d\n", cube.num_binary_vars); - if (cube.output != -1) - fprintf(fp, ".o %d\n", cube.part_size[cube.output]); - } else { - fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars); - for(var = cube.num_binary_vars; var < cube.num_vars; var++) - fprintf(fp, " %d", cube.part_size[var]); - fprintf(fp, "\n"); - } - - /* binary valued labels */ - if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char) - && cube.num_binary_vars > 0) { - fprintf(fp, ".ilb"); - for(var = 0; var < cube.num_binary_vars; var++) - fprintf(fp, " %s", INLABEL(var)); - putc('\n', fp); - } - - /* output-part (last multiple-valued variable) labels */ - if (PLA->label != NIL(char *) && - PLA->label[cube.first_part[cube.output]] != NIL(char) - && cube.output != -1) { - fprintf(fp, ".ob"); - for(i = 0; i < cube.part_size[cube.output]; i++) - fprintf(fp, " %s", OUTLABEL(i)); - putc('\n', fp); - } - - /* multiple-valued labels */ - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { - first = cube.first_part[var]; - last = cube.last_part[var]; - if (PLA->label != NULL && PLA->label[first] != NULL) { - fprintf(fp, ".label var=%d", var); - for(i = first; i <= last; i++) { - fprintf(fp, " %s", PLA->label[i]); - } - putc('\n', fp); - } - } - - if (PLA->phase != (pcube) NULL) { - first = cube.first_part[cube.output]; - last = cube.last_part[cube.output]; - fprintf(fp, "#.phase "); - for(i = first; i <= last; i++) - putc(is_in_set(PLA->phase,i) ? '1' : '0', fp); - fprintf(fp, "\n"); - } -} - -void pls_output(PLA) -IN pPLA PLA; -{ - register pcube last, p; - - printf(".option unmerged\n"); - makeup_labels(PLA); - pls_label(PLA, stdout); - pls_group(PLA, stdout); - printf(".p %d\n", PLA->F->count); - foreach_set(PLA->F, last, p) { - print_expanded_cube(stdout, p, PLA->phase); - } - printf(".end\n"); -} - - -void pls_group(PLA, fp) -pPLA PLA; -FILE *fp; -{ - int var, i, col, len; - - fprintf(fp, "\n.group"); - col = 6; - for(var = 0; var < cube.num_vars-1; var++) { - fprintf(fp, " ("), col += 2; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - len = strlen(PLA->label[i]); - if (col + len > 75) - fprintf(fp, " \\\n"), col = 0; - else if (i != 0) - putc(' ', fp), col += 1; - fprintf(fp, "%s", PLA->label[i]), col += len; - } - fprintf(fp, ")"), col += 1; - } - fprintf(fp, "\n"); -} - - -void pls_label(PLA, fp) -pPLA PLA; -FILE *fp; -{ - int var, i, col, len; - - fprintf(fp, ".label"); - col = 6; - for(var = 0; var < cube.num_vars; var++) - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - len = strlen(PLA->label[i]); - if (col + len > 75) - fprintf(fp, " \\\n"), col = 0; - else - putc(' ', fp), col += 1; - fprintf(fp, "%s", PLA->label[i]), col += len; - } -} - - - -/* - eqntott output mode -- output algebraic equations -*/ -void eqn_output(PLA) -pPLA PLA; -{ - register pcube p, last; - register int i, var, col, len; - int x; - bool firstand, firstor; - - if (cube.output == -1) - fatal("Cannot have no-output function for EQNTOTT output mode"); - if (cube.num_mv_vars != 1) - fatal("Must have binary-valued function for EQNTOTT output mode"); - makeup_labels(PLA); - - /* Write a single equation for each output */ - for(i = 0; i < cube.part_size[cube.output]; i++) { - printf("%s = ", OUTLABEL(i)); - col = strlen(OUTLABEL(i)) + 3; - firstor = TRUE; - - /* Write product terms for each cube in this output */ - foreach_set(PLA->F, last, p) - if (is_in_set(p, i + cube.first_part[cube.output])) { - if (firstor) - printf("("), col += 1; - else - printf(" | ("), col += 4; - firstor = FALSE; - firstand = TRUE; - - /* print out a product term */ - for(var = 0; var < cube.num_binary_vars; var++) - if ((x=GETINPUT(p, var)) != DASH) { - len = strlen(INLABEL(var)); - if (col+len > 72) - printf("\n "), col = 4; - if (! firstand) - printf("&"), col += 1; - firstand = FALSE; - if (x == ZERO) - printf("!"), col += 1; - printf("%s", INLABEL(var)), col += len; - } - printf(")"), col += 1; - } - printf(";\n\n"); - } -} - - -char *fmt_cube(c, out_map, s) -register pcube c; -register char *out_map, *s; -{ - register int i, var, last, len = 0; - - for(var = 0; var < cube.num_binary_vars; var++) { - s[len++] = "?01-" [GETINPUT(c, var)]; - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - s[len++] = ' '; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - s[len++] = "01" [is_in_set(c, i) != 0]; - } - } - if (cube.output != -1) { - last = cube.last_part[cube.output]; - s[len++] = ' '; - for(i = cube.first_part[cube.output]; i <= last; i++) { - s[len++] = out_map [is_in_set(c, i) != 0]; - } - } - s[len] = '\0'; - return s; -} - - -void print_cube(fp, c, out_map) -register FILE *fp; -register pcube c; -register char *out_map; -{ - register int i, var, ch; - int last; - - for(var = 0; var < cube.num_binary_vars; var++) { - ch = "?01-" [GETINPUT(c, var)]; - putc(ch, fp); - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "01" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - if (cube.output != -1) { - last = cube.last_part[cube.output]; - putc(' ', fp); - for(i = cube.first_part[cube.output]; i <= last; i++) { - ch = out_map [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - putc('\n', fp); -} - - -void print_expanded_cube(fp, c, phase) -register FILE *fp; -register pcube c; -pcube phase; -{ - register int i, var, ch; - char *out_map; - - for(var = 0; var < cube.num_binary_vars; var++) { - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "~1" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "1~" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - if (cube.output != -1) { - var = cube.num_vars - 1; - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (phase == (pcube) NULL || is_in_set(phase, i)) { - out_map = "~1"; - } else { - out_map = "~0"; - } - ch = out_map[is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - putc('\n', fp); -} - - -char *pc1(c) pcube c; -{static char s1[256];return fmt_cube(c, "01", s1);} -char *pc2(c) pcube c; -{static char s2[256];return fmt_cube(c, "01", s2);} - - -void debug_print(T, name, level) -pcube *T; -char *name; -int level; -{ - register pcube *T1, p, temp; - register int cnt; - - cnt = CUBELISTSIZE(T); - temp = new_cube(); - if (verbose_debug && level == 0) - printf("\n"); - printf("%s[%d]: ord(T)=%d\n", name, level, cnt); - if (verbose_debug) { - printf("cofactor=%s\n", pc1(T[0])); - for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++) - printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0]))); - } - free_cube(temp); -} - - -void debug1_print(T, name, num) -pcover T; -char *name; -int num; -{ - register int cnt = 1; - register pcube p, last; - - if (verbose_debug && num == 0) - printf("\n"); - printf("%s[%d]: ord(T)=%d\n", name, num, T->count); - if (verbose_debug) - foreach_set(T, last, p) - printf("%4d. %s\n", cnt++, pc1(p)); -} - - -void cprint(T) -pcover T; -{ - register pcube p, last; - - foreach_set(T, last, p) - printf("%s\n", pc1(p)); -} - - -int makeup_labels(PLA) -pPLA PLA; -{ - int var, i, ind; - - if (PLA->label == (char **) NULL) - PLA_labels(PLA); - - for(var = 0; var < cube.num_vars; var++) - for(i = 0; i < cube.part_size[var]; i++) { - ind = cube.first_part[var] + i; - if (PLA->label[ind] == (char *) NULL) { - PLA->label[ind] = ALLOC(char, 15); - if (var < cube.num_binary_vars) - if ((i % 2) == 0) - (void) sprintf(PLA->label[ind], "v%d.bar", var); - else - (void) sprintf(PLA->label[ind], "v%d", var); - else - (void) sprintf(PLA->label[ind], "v%d.%d", var, i); - } - } -} - - -kiss_output(fp, PLA) -FILE *fp; -pPLA PLA; -{ - register pset last, p; - - foreach_set(PLA->F, last, p) { - kiss_print_cube(fp, PLA, p, "~1"); - } - foreach_set(PLA->D, last, p) { - kiss_print_cube(fp, PLA, p, "~2"); - } -} - - -kiss_print_cube(fp, PLA, p, out_string) -FILE *fp; -pPLA PLA; -pcube p; -char *out_string; -{ - register int i, var; - int part, x; - - for(var = 0; var < cube.num_binary_vars; var++) { - x = "?01-" [GETINPUT(p, var)]; - putc(x, fp); - } - - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - putc(' ', fp); - if (setp_implies(cube.var_mask[var], p)) { - putc('-', fp); - } else { - part = -1; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (is_in_set(p, i)) { - if (part != -1) { - fatal("more than 1 part in a symbolic variable\n"); - } - part = i; - } - } - if (part == -1) { - putc('~', fp); /* no parts, hope its an output ... */ - } else { - (void) fputs(PLA->label[part], fp); - } - } - } - - if ((var = cube.output) != -1) { - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - x = out_string [is_in_set(p, i) != 0]; - putc(x, fp); - } - } - - putc('\n', fp); -} - -output_symbolic_constraints(fp, PLA, output_symbolic) -FILE *fp; -pPLA PLA; -int output_symbolic; -{ - pset_family A; - register int i, j; - int size, var, npermute, *permute, *weight, noweight; - - if ((cube.num_vars - cube.num_binary_vars) <= 1) { - return 0; - } - makeup_labels(PLA); - - for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) { - - /* pull out the columns for variable "var" */ - npermute = cube.part_size[var]; - permute = ALLOC(int, npermute); - for(i=0; i < npermute; i++) { - permute[i] = cube.first_part[var] + i; - } - A = sf_permute(sf_save(PLA->F), permute, npermute); - FREE(permute); - - - /* Delete the singletons and the full sets */ - noweight = 0; - for(i = 0; i < A->count; i++) { - size = set_ord(GETSET(A,i)); - if (size == 1 || size == A->sf_size) { - sf_delset(A, i--); - noweight++; - } - } - - - /* Count how many times each is duplicated */ - weight = ALLOC(int, A->count); - for(i = 0; i < A->count; i++) { - RESET(GETSET(A, i), COVERED); - } - for(i = 0; i < A->count; i++) { - weight[i] = 0; - if (! TESTP(GETSET(A,i), COVERED)) { - weight[i] = 1; - for(j = i+1; j < A->count; j++) { - if (setp_equal(GETSET(A,i), GETSET(A,j))) { - weight[i]++; - SET(GETSET(A,j), COVERED); - } - } - } - } - - - /* Print out the contraints */ - if (! output_symbolic) { - (void) fprintf(fp, - "# Symbolic constraints for variable %d (Numeric form)\n", var); - (void) fprintf(fp, "# unconstrained weight = %d\n", noweight); - (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]); - for(i = 0; i < A->count; i++) { - if (weight[i] > 0) { - (void) fprintf(fp, "weight=%d: ", weight[i]); - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(GETSET(A,i), j)) { - (void) fprintf(fp, " %d", j); - } - } - (void) fprintf(fp, "\n"); - } - } - } else { - (void) fprintf(fp, - "# Symbolic constraints for variable %d (Symbolic form)\n", var); - for(i = 0; i < A->count; i++) { - if (weight[i] > 0) { - (void) fprintf(fp, "# w=%d: (", weight[i]); - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(GETSET(A,i), j)) { - (void) fprintf(fp, " %s", - PLA->label[cube.first_part[var]+j]); - } - } - (void) fprintf(fp, " )\n"); - } - } - FREE(weight); - } - } -} diff --git a/src/benchmarks/espresso/dominate.c b/src/benchmarks/espresso/dominate.c deleted file mode 100644 index 882a43c..0000000 --- a/src/benchmarks/espresso/dominate.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - - -int -sm_row_dominance(A) -sm_matrix *A; -{ - register sm_row *prow, *prow1; - register sm_col *pcol, *least_col; - register sm_element *p, *pnext; - int rowcnt; - - rowcnt = A->nrows; - - /* Check each row against all other rows */ - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - - /* Among all columns with a 1 in this row, choose smallest */ - least_col = sm_get_col(A, prow->first_col->col_num); - for(p = prow->first_col->next_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - if (pcol->length < least_col->length) { - least_col = pcol; - } - } - - /* Only check for containment against rows in this column */ - for(p = least_col->first_row; p != 0; p = pnext) { - pnext = p->next_row; - - prow1 = sm_get_row(A, p->row_num); - if ((prow1->length > prow->length) || - (prow1->length == prow->length && - prow1->row_num > prow->row_num)) { - if (sm_row_contains(prow, prow1)) { - sm_delrow(A, prow1->row_num); - } - } - } - } - - return rowcnt - A->nrows; -} - -int -sm_col_dominance(A, weight) -sm_matrix *A; -int *weight; -{ - register sm_row *prow; - register sm_col *pcol, *pcol1; - register sm_element *p; - sm_row *least_row; - sm_col *next_col; - int colcnt; - - colcnt = A->ncols; - - /* Check each column against all other columns */ - for(pcol = A->first_col; pcol != 0; pcol = next_col) { - next_col = pcol->next_col; - - /* Check all rows to find the one with fewest elements */ - least_row = sm_get_row(A, pcol->first_row->row_num); - for(p = pcol->first_row->next_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - if (prow->length < least_row->length) { - least_row = prow; - } - } - - /* Only check for containment against columns in this row */ - for(p = least_row->first_col; p != 0; p = p->next_col) { - pcol1 = sm_get_col(A, p->col_num); - if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num]) - continue; - if ((pcol1->length > pcol->length) || - (pcol1->length == pcol->length && - pcol1->col_num > pcol->col_num)) { - if (sm_col_contains(pcol, pcol1)) { - sm_delcol(A, pcol->col_num); - break; - } - } - } - } - - return colcnt - A->ncols; -} diff --git a/src/benchmarks/espresso/equiv.c b/src/benchmarks/espresso/equiv.c deleted file mode 100644 index be10542..0000000 --- a/src/benchmarks/espresso/equiv.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "espresso.h" - - -find_equiv_outputs(PLA) -pPLA PLA; -{ - int i, j, ipart, jpart, some_equiv; - pcover *R, *F; - - some_equiv = FALSE; - - makeup_labels(PLA); - - F = ALLOC(pcover, cube.part_size[cube.output]); - R = ALLOC(pcover, cube.part_size[cube.output]); - - for(i = 0; i < cube.part_size[cube.output]; i++) { - ipart = cube.first_part[cube.output] + i; - R[i] = cof_output(PLA->R, ipart); - F[i] = complement(cube1list(R[i])); - } - - for(i = 0; i < cube.part_size[cube.output]-1; i++) { - for(j = i+1; j < cube.part_size[cube.output]; j++) { - ipart = cube.first_part[cube.output] + i; - jpart = cube.first_part[cube.output] + j; - - if (check_equiv(F[i], F[j])) { - printf("# Outputs %d and %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(F[i], R[j])) { - printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(R[i], F[j])) { - printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(R[i], R[j])) { - printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } - } - } - - if (! some_equiv) { - printf("# No outputs are equivalent\n"); - } - - for(i = 0; i < cube.part_size[cube.output]; i++) { - free_cover(F[i]); - free_cover(R[i]); - } - FREE(F); - FREE(R); -} - - - -int check_equiv(f1, f2) -pcover f1, f2; -{ - register pcube *f1list, *f2list; - register pcube p, last; - - f1list = cube1list(f1); - foreach_set(f2, last, p) { - if (! cube_is_covered(f1list, p)) { - return FALSE; - } - } - free_cubelist(f1list); - - f2list = cube1list(f2); - foreach_set(f1, last, p) { - if (! cube_is_covered(f2list, p)) { - return FALSE; - } - } - free_cubelist(f2list); - - return TRUE; -} diff --git a/src/benchmarks/espresso/espresso.c b/src/benchmarks/espresso/espresso.c deleted file mode 100644 index 41dc1d3..0000000 --- a/src/benchmarks/espresso/espresso.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Module: espresso.c - * Purpose: The main espresso algorithm - * - * Returns a minimized version of the ON-set of a function - * - * The following global variables affect the operation of Espresso: - * - * MISCELLANEOUS: - * trace - * print trace information as the minimization progresses - * - * remove_essential - * remove essential primes - * - * single_expand - * if true, stop after first expand/irredundant - * - * LAST_GASP or SUPER_GASP strategy: - * use_super_gasp - * uses the super_gasp strategy rather than last_gasp - * - * SETUP strategy: - * recompute_onset - * recompute onset using the complement before starting - * - * unwrap_onset - * unwrap the function output part before first expand - * - * MAKE_SPARSE strategy: - * force_irredundant - * iterates make_sparse to force a minimal solution (used - * indirectly by make_sparse) - * - * skip_make_sparse - * skip the make_sparse step (used by opo only) - */ - -#include "espresso.h" - -pcover espresso(F, D1, R) -pcover F, D1, R; -{ - pcover E, D, Fsave; - pset last, p; - cost_t cost, best_cost; - -begin: - Fsave = sf_save(F); /* save original function */ - D = sf_save(D1); /* make a scratch copy of D */ - - /* Setup has always been a problem */ - if (recompute_onset) { - EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E); - free_cover(F); - F = E; - } - cover_cost(F, &cost); - if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1) - && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1]) - && (cost.out < 5000)) - EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F); - - /* Initial expand and irredundant */ - foreach_set(F, last, p) { - RESET(p, PRIME); - } - EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); - EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); - - if (! single_expand) { - if (remove_essential) { - EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost); - } else { - E = new_cover(0); - } - - cover_cost(F, &cost); - do { - - /* Repeat inner loop until solution becomes "stable" */ - do { - copy_cost(&cost, &best_cost); - EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost); - EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); - EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); - } while (cost.cubes < best_cost.cubes); - - /* Perturb solution to see if we can continue to iterate */ - copy_cost(&cost, &best_cost); - if (use_super_gasp) { - F = super_gasp(F, D, R, &cost); - if (cost.cubes >= best_cost.cubes) - break; - } else { - F = last_gasp(F, D, R, &cost); - } - - } while (cost.cubes < best_cost.cubes || - (cost.cubes == best_cost.cubes && cost.total < best_cost.total)); - - /* Append the essential cubes to F */ - F = sf_append(F, E); /* disposes of E */ - if (trace) size_stamp(F, "ADJUST "); - } - - /* Free the D which we used */ - free_cover(D); - - /* Attempt to make the PLA matrix sparse */ - if (! skip_make_sparse) { - F = make_sparse(F, D1, R); - } - - /* - * Check to make sure function is actually smaller !! - * This can only happen because of the initial unravel. If we fail, - * then run the whole thing again without the unravel. - */ - if (Fsave->count < F->count) { - free_cover(F); - F = Fsave; - unwrap_onset = FALSE; - goto begin; - } else { - free_cover(Fsave); - } - - return F; -} diff --git a/src/benchmarks/espresso/espresso.h b/src/benchmarks/espresso/espresso.h deleted file mode 100644 index 38670e4..0000000 --- a/src/benchmarks/espresso/espresso.h +++ /dev/null @@ -1,772 +0,0 @@ -#if defined(USE_LOCH) && defined(_WIN32) -#pragma comment(lib, "loch.lib") -#endif - -/* - * espresso.h -- header file for Espresso-mv - */ - -#include "port.h" -#include "utility.h" -#include "sparse.h" -#include "mincov.h" - -#define ptime() util_cpu_time() -#define print_time(t) util_print_time(t) - -#ifdef IBM_WATC -#define void int -#include "short.h" -#endif - -#ifdef IBMPC /* set default options for IBM/PC */ -#define NO_INLINE -#define BPI 16 -#endif - -/*-----THIS USED TO BE set.h----- */ - -/* - * set.h -- definitions for packed arrays of bits - * - * This header file describes the data structures which comprise a - * facility for efficiently implementing packed arrays of bits - * (otherwise known as sets, cf. Pascal). - * - * A set is a vector of bits and is implemented here as an array of - * unsigned integers. The low order bits of set[0] give the index of - * the last word of set data. The higher order bits of set[0] are - * used to store data associated with the set. The set data is - * contained in elements set[1] ... set[LOOP(set)] as a packed bit - * array. - * - * A family of sets is a two-dimensional matrix of bits and is - * implemented with the data type "set_family". - * - * BPI == 32 and BPI == 16 have been tested and work. - */ - - -/* Define host machine characteristics of "unsigned int" */ -#ifndef BPI -#define BPI 32 /* # bits per integer */ -#endif - -#if BPI == 32 -#define LOGBPI 5 /* log(BPI)/log(2) */ -#else -#define LOGBPI 4 /* log(BPI)/log(2) */ -#endif - -/* Define the set type */ -typedef unsigned int *pset; - -/* Define the set family type -- an array of sets */ -typedef struct set_family { - int wsize; /* Size of each set in 'ints' */ - int sf_size; /* User declared set size */ - int capacity; /* Number of sets allocated */ - int count; /* The number of sets in the family */ - int active_count; /* Number of "active" sets */ - pset data; /* Pointer to the set data */ - struct set_family *next; /* For garbage collection */ -} set_family_t, *pset_family; - -/* Macros to set and test single elements */ -#define WHICH_WORD(element) (((element) >> LOGBPI) + 1) -#define WHICH_BIT(element) ((element) & (BPI-1)) - -/* # of ints needed to allocate a set with "size" elements */ -#if BPI == 32 -#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1)) -#else -#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2)) -#endif - -/* - * Three fields are maintained in the first word of the set - * LOOP is the index of the last word used for set data - * LOOPCOPY is the index of the last word in the set - * SIZE is available for general use (e.g., recording # elements in set) - * NELEM retrieves the number of elements in the set - */ -#define LOOP(set) (set[0] & 0x03ff) -#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i)) -#if BPI == 32 -#define LOOPCOPY(set) LOOP(set) -#define SIZE(set) (set[0] >> 16) -#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16)) -#else -#define LOOPCOPY(set) (LOOP(set) + 1) -#define SIZE(set) (set[LOOP(set)+1]) -#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size)) -#endif - -#define NELEM(set) (BPI * LOOP(set)) -#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1)) - -/* - * FLAGS store general information about the set - */ -#define SET(set, flag) (set[0] |= (flag)) -#define RESET(set, flag) (set[0] &= ~ (flag)) -#define TESTP(set, flag) (set[0] & (flag)) - -/* Flag definitions are ... */ -#define PRIME 0x8000 /* cube is prime */ -#define NONESSEN 0x4000 /* cube cannot be essential prime */ -#define ACTIVE 0x2000 /* cube is still active */ -#define REDUND 0x1000 /* cube is redundant(at this point) */ -#define COVERED 0x0800 /* cube has been covered */ -#define RELESSEN 0x0400 /* cube is relatively essential */ - -/* Most efficient way to look at all members of a set family */ -#define foreach_set(R, last, p)\ - for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize) -#define foreach_remaining_set(R, last, pfirst, p)\ - for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize) -#define foreach_active_set(R, last, p)\ - foreach_set(R,last,p) if (TESTP(p, ACTIVE)) - -/* Another way that also keeps the index of the current set member in i */ -#define foreachi_set(R, i, p)\ - for(p=R->data,i=0;i<R->count;p+=R->wsize,i++) -#define foreachi_active_set(R, i, p)\ - foreachi_set(R,i,p) if (TESTP(p, ACTIVE)) - -/* Looping over all elements in a set: - * foreach_set_element(pset p, int i, unsigned val, int base) { - * . - * . - * . - * } - */ -#define foreach_set_element(p, i, val, base) \ - for(i = LOOP(p); i > 0; ) \ - for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \ - if (val & 1) - -/* Return a pointer to a given member of a set family */ -#define GETSET(family, index) ((family)->data + (family)->wsize * (index)) - -/* Allocate and deallocate sets */ -#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size) -#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size) -#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r) -#define set_free(r) FREE(r) - -/* Check for set membership, remove set element and insert set element */ -#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e))) -#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e))) -#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e)) - -/* Inline code substitution for those places that REALLY need it on a VAX */ -#ifdef NO_INLINE -#define INLINEset_copy(r, a) (void) set_copy(r,a) -#define INLINEset_clear(r, size) (void) set_clear(r, size) -#define INLINEset_fill(r, size) (void) set_fill(r, size) -#define INLINEset_and(r, a, b) (void) set_and(r, a, b) -#define INLINEset_or(r, a, b) (void) set_or(r, a, b) -#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b) -#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f) -#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) -#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) -#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask) -#define INLINEsetp_implies(a, b, when_false) \ - if (! setp_implies(a,b)) when_false -#define INLINEsetp_disjoint(a, b, when_false) \ - if (! setp_disjoint(a,b)) when_false -#define INLINEsetp_equal(a, b, when_false) \ - if (! setp_equal(a,b)) when_false - -#else - -#define INLINEset_copy(r, a)\ - {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);} -#define INLINEset_clear(r, size)\ - {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);} -#define INLINEset_fill(r, size)\ - {register int i_=LOOPINIT(size); *r=i_; \ - r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;} -#define INLINEset_and(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] & b[i_]; while (--i_>0);} -#define INLINEset_or(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] | b[i_]; while (--i_>0);} -#define INLINEset_diff(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);} -#define INLINEset_ndiff(r, a, b, fullset)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);} -#ifdef IBM_WATC -#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) -#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) -#else -#define INLINEset_xor(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] ^ b[i_]; while (--i_>0);} -#define INLINEset_xnor(r, a, b, fullset)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);} -#endif -#define INLINEset_merge(r, a, b, mask)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);} -#define INLINEsetp_implies(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} -#define INLINEsetp_disjoint(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} -#define INLINEsetp_equal(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} - -#endif - -#if BPI == 32 -#define count_ones(v)\ - (bit_count[v & 255] + bit_count[(v >> 8) & 255]\ - + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255]) -#else -#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255]) -#endif - -/* Table for efficient bit counting */ -extern int bit_count[256]; -/*----- END OF set.h ----- */ - -/* Define a boolean type */ -#define bool int -#define FALSE 0 -#define TRUE 1 -#define MAYBE 2 -#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE")) - -/* Map many cube/cover types/routines into equivalent set types/routines */ -#define pcube pset -#define new_cube() set_new(cube.size) -#define free_cube(r) set_free(r) -#define pcover pset_family -#define new_cover(i) sf_new(i, cube.size) -#define free_cover(r) sf_free(r) -#define free_cubelist(T) FREE(T[0]); FREE(T); - - -/* cost_t describes the cost of a cover */ -typedef struct cost_struct { - int cubes; /* number of cubes in the cover */ - int in; /* transistor count, binary-valued variables */ - int out; /* transistor count, output part */ - int mv; /* transistor count, multiple-valued vars */ - int total; /* total number of transistors */ - int primes; /* number of prime cubes */ -} cost_t, *pcost; - - -/* pair_t describes bit-paired variables */ -typedef struct pair_struct { - int cnt; - int *var1; - int *var2; -} pair_t, *ppair; - - -/* symbolic_list_t describes a single ".symbolic" line */ -typedef struct symbolic_list_struct { - int variable; - int pos; - struct symbolic_list_struct *next; -} symbolic_list_t; - - -/* symbolic_list_t describes a single ".symbolic" line */ -typedef struct symbolic_label_struct { - char *label; - struct symbolic_label_struct *next; -} symbolic_label_t; - - -/* symbolic_t describes a linked list of ".symbolic" lines */ -typedef struct symbolic_struct { - symbolic_list_t *symbolic_list; /* linked list of items */ - int symbolic_list_length; /* length of symbolic_list list */ - symbolic_label_t *symbolic_label; /* linked list of new names */ - int symbolic_label_length; /* length of symbolic_label list */ - struct symbolic_struct *next; -} symbolic_t; - - -/* PLA_t stores the logical representation of a PLA */ -typedef struct { - pcover F, D, R; /* on-set, off-set and dc-set */ - char *filename; /* filename */ - int pla_type; /* logical PLA format */ - pcube phase; /* phase to split into on-set and off-set */ - ppair pair; /* how to pair variables */ - char **label; /* labels for the columns */ - symbolic_t *symbolic; /* allow binary->symbolic mapping */ - symbolic_t *symbolic_output;/* allow symbolic output mapping */ -} PLA_t, *pPLA; - -#define equal(a,b) (strcmp(a,b) == 0) - -/* This is a hack which I wish I hadn't done, but too painful to change */ -#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3) - -/* For documentation purposes */ -#define IN -#define OUT -#define INOUT - -/* The pla_type field describes the input and output format of the PLA */ -#define F_type 1 -#define D_type 2 -#define R_type 4 -#define PLEASURE_type 8 /* output format */ -#define EQNTOTT_type 16 /* output format algebraic eqns */ -#define KISS_type 128 /* output format kiss */ -#define CONSTRAINTS_type 256 /* output the constraints (numeric) */ -#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */ -#define FD_type (F_type | D_type) -#define FR_type (F_type | R_type) -#define DR_type (D_type | R_type) -#define FDR_type (F_type | D_type | R_type) - -/* Definitions for the debug variable */ -#define COMPL 0x0001 -#define ESSEN 0x0002 -#define EXPAND 0x0004 -#define EXPAND1 0x0008 -#define GASP 0x0010 -#define IRRED 0x0020 -#define REDUCE 0x0040 -#define REDUCE1 0x0080 -#define SPARSE 0x0100 -#define TAUT 0x0200 -#define EXACT 0x0400 -#define MINCOV 0x0800 -#define MINCOV1 0x1000 -#define SHARP 0x2000 -#define IRRED1 0x4000 - -#define VERSION\ - "UC Berkeley, Espresso Version #2.3, Release date 01/31/88" - -/* Define constants used for recording program statistics */ -#define TIME_COUNT 16 -#define READ_TIME 0 -#define COMPL_TIME 1 -#define ONSET_TIME 2 -#define ESSEN_TIME 3 -#define EXPAND_TIME 4 -#define IRRED_TIME 5 -#define REDUCE_TIME 6 -#define GEXPAND_TIME 7 -#define GIRRED_TIME 8 -#define GREDUCE_TIME 9 -#define PRIMES_TIME 10 -#define MINCOV_TIME 11 -#define MV_REDUCE_TIME 12 -#define RAISE_IN_TIME 13 -#define VERIFY_TIME 14 -#define WRITE_TIME 15 - - -/* For those who like to think about PLAs, macros to get at inputs/outputs */ -#define NUMINPUTS cube.num_binary_vars -#define NUMOUTPUTS cube.part_size[cube.num_vars - 1] - -#define POSITIVE_PHASE(pos)\ - (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0) - -#define INLABEL(var) PLA->label[cube.first_part[var] + 1] -#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos] - -#define GETINPUT(c, pos)\ - ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3) -#define GETOUTPUT(c, pos)\ - (is_in_set(c, cube.first_part[cube.output] + pos) != 0) - -#define PUTINPUT(c, pos, value)\ - c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\ - | (value << WHICH_BIT(2*pos)) -#define PUTOUTPUT(c, pos, value)\ - c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & (1 << WHICH_BIT(pos)))\ - | (value << WHICH_BIT(pos)) - -#define TWO 3 -#define DASH 3 -#define ONE 2 -#define ZERO 1 - - -#define EXEC(fct, name, S)\ - {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);} -#define EXEC_S(fct, name, S)\ - {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);} -#define EXECUTE(fct,i,S,cost)\ - {long t=ptime();fct;totals(t,i,S,&(cost));} - -/* - * Global Variable Declarations - */ - -extern unsigned int debug; /* debug parameter */ -extern bool verbose_debug; /* -v: whether to print a lot */ -extern char *total_name[TIME_COUNT]; /* basic function names */ -extern long total_time[TIME_COUNT]; /* time spent in basic fcts */ -extern int total_calls[TIME_COUNT]; /* # calls to each fct */ - -extern bool echo_comments; /* turned off by -eat option */ -extern bool echo_unknown_commands; /* always true ?? */ -extern bool force_irredundant; /* -nirr command line option */ -extern bool skip_make_sparse; -extern bool kiss; /* -kiss command line option */ -extern bool pos; /* -pos command line option */ -extern bool print_solution; /* -x command line option */ -extern bool recompute_onset; /* -onset command line option */ -extern bool remove_essential; /* -ness command line option */ -extern bool single_expand; /* -fast command line option */ -extern bool summary; /* -s command line option */ -extern bool trace; /* -t command line option */ -extern bool unwrap_onset; /* -nunwrap command line option */ -extern bool use_random_order; /* -random command line option */ -extern bool use_super_gasp; /* -strong command line option */ -extern char *filename; /* filename PLA was read from */ -extern bool debug_exact_minimization; /* dumps info for -do exact */ - - -/* - * pla_types are the input and output types for reading/writing a PLA - */ -struct pla_types_struct { - char *key; - int value; -}; - - -/* - * The cube structure is a global structure which contains information - * on how a set maps into a cube -- i.e., number of parts per variable, - * number of variables, etc. Also, many fields are pre-computed to - * speed up various primitive operations. - */ -#define CUBE_TEMP 10 - -struct cube_struct { - int size; /* set size of a cube */ - int num_vars; /* number of variables in a cube */ - int num_binary_vars; /* number of binary variables */ - int *first_part; /* first element of each variable */ - int *last_part; /* first element of each variable */ - int *part_size; /* number of elements in each variable */ - int *first_word; /* first word for each variable */ - int *last_word; /* last word for each variable */ - pset binary_mask; /* Mask to extract binary variables */ - pset mv_mask; /* mask to get mv parts */ - pset *var_mask; /* mask to extract a variable */ - pset *temp; /* an array of temporary sets */ - pset fullset; /* a full cube */ - pset emptyset; /* an empty cube */ - unsigned int inmask; /* mask to get odd word of binary part */ - int inword; /* which word number for above */ - int *sparse; /* should this variable be sparse? */ - int num_mv_vars; /* number of multiple-valued variables */ - int output; /* which variable is "output" (-1 if none) */ -}; - -struct cdata_struct { - int *part_zeros; /* count of zeros for each element */ - int *var_zeros; /* count of zeros for each variable */ - int *parts_active; /* number of "active" parts for each var */ - bool *is_unate; /* indicates given var is unate */ - int vars_active; /* number of "active" variables */ - int vars_unate; /* number of unate variables */ - int best; /* best "binate" variable */ -}; - - -extern struct pla_types_struct pla_types[]; -extern struct cube_struct cube, temp_cube_save; -extern struct cdata_struct cdata, temp_cdata_save; - -#ifdef lint -#define DISJOINT 0x5555 -#else -#if BPI == 32 -#define DISJOINT 0x55555555 -#else -#define DISJOINT 0x5555 -#endif -#endif - -/* function declarations */ - -/* cofactor.c */ extern int binate_split_select(); -/* cofactor.c */ extern pcover cubeunlist(); -/* cofactor.c */ extern pcube *cofactor(); -/* cofactor.c */ extern pcube *cube1list(); -/* cofactor.c */ extern pcube *cube2list(); -/* cofactor.c */ extern pcube *cube3list(); -/* cofactor.c */ extern pcube *scofactor(); -/* cofactor.c */ extern void massive_count(); -/* compl.c */ extern pcover complement(); -/* compl.c */ extern pcover simplify(); -/* compl.c */ extern void simp_comp(); -/* contain.c */ extern int d1_rm_equal(); -/* contain.c */ extern int rm2_contain(); -/* contain.c */ extern int rm2_equal(); -/* contain.c */ extern int rm_contain(); -/* contain.c */ extern int rm_equal(); -/* contain.c */ extern int rm_rev_contain(); -/* contain.c */ extern pset *sf_list(); -/* contain.c */ extern pset *sf_sort(); -/* contain.c */ extern pset_family d1merge(); -/* contain.c */ extern pset_family dist_merge(); -/* contain.c */ extern pset_family sf_contain(); -/* contain.c */ extern pset_family sf_dupl(); -/* contain.c */ extern pset_family sf_ind_contain(); -/* contain.c */ extern pset_family sf_ind_unlist(); -/* contain.c */ extern pset_family sf_merge(); -/* contain.c */ extern pset_family sf_rev_contain(); -/* contain.c */ extern pset_family sf_union(); -/* contain.c */ extern pset_family sf_unlist(); -/* cubestr.c */ extern void cube_setup(); -/* cubestr.c */ extern void restore_cube_struct(); -/* cubestr.c */ extern void save_cube_struct(); -/* cubestr.c */ extern void setdown_cube(); -/* cvrin.c */ extern PLA_labels(); -/* cvrin.c */ extern char *get_word(); -/* cvrin.c */ extern int label_index(); -/* cvrin.c */ extern int read_pla(); -/* cvrin.c */ extern int read_symbolic(); -/* cvrin.c */ extern pPLA new_PLA(); -/* cvrin.c */ extern void PLA_summary(); -/* cvrin.c */ extern void free_PLA(); -/* cvrin.c */ extern void parse_pla(); -/* cvrin.c */ extern void read_cube(); -/* cvrin.c */ extern void skip_line(); -/* cvrm.c */ extern foreach_output_function(); -/* cvrm.c */ extern int cubelist_partition(); -/* cvrm.c */ extern int so_both_do_espresso(); -/* cvrm.c */ extern int so_both_do_exact(); -/* cvrm.c */ extern int so_both_save(); -/* cvrm.c */ extern int so_do_espresso(); -/* cvrm.c */ extern int so_do_exact(); -/* cvrm.c */ extern int so_save(); -/* cvrm.c */ extern pcover cof_output(); -/* cvrm.c */ extern pcover lex_sort(); -/* cvrm.c */ extern pcover mini_sort(); -/* cvrm.c */ extern pcover random_order(); -/* cvrm.c */ extern pcover size_sort(); -/* cvrm.c */ extern pcover sort_reduce(); -/* cvrm.c */ extern pcover uncof_output(); -/* cvrm.c */ extern pcover unravel(); -/* cvrm.c */ extern pcover unravel_range(); -/* cvrm.c */ extern void so_both_espresso(); -/* cvrm.c */ extern void so_espresso(); -/* cvrmisc.c */ extern char *fmt_cost(); -/* cvrmisc.c */ extern char *print_cost(); -/* cvrmisc.c */ extern char *strsav(); -/* cvrmisc.c */ extern void copy_cost(); -/* cvrmisc.c */ extern void cover_cost(); -/* cvrmisc.c */ extern void fatal(); -/* cvrmisc.c */ extern void print_trace(); -/* cvrmisc.c */ extern void size_stamp(); -/* cvrmisc.c */ extern void totals(); -/* cvrout.c */ extern char *fmt_cube(); -/* cvrout.c */ extern char *fmt_expanded_cube(); -/* cvrout.c */ extern char *pc1(); -/* cvrout.c */ extern char *pc2(); -/* cvrout.c */ extern char *pc3(); -/* cvrout.c */ extern int makeup_labels(); -/* cvrout.c */ extern kiss_output(); -/* cvrout.c */ extern kiss_print_cube(); -/* cvrout.c */ extern output_symbolic_constraints(); -/* cvrout.c */ extern void cprint(); -/* cvrout.c */ extern void debug1_print(); -/* cvrout.c */ extern void debug_print(); -/* cvrout.c */ extern void eqn_output(); -/* cvrout.c */ extern void fpr_header(); -/* cvrout.c */ extern void fprint_pla(); -/* cvrout.c */ extern void pls_group(); -/* cvrout.c */ extern void pls_label(); -/* cvrout.c */ extern void pls_output(); -/* cvrout.c */ extern void print_cube(); -/* cvrout.c */ extern void print_expanded_cube(); -/* cvrout.c */ extern void sf_debug_print(); -/* equiv.c */ extern find_equiv_outputs(); -/* equiv.c */ extern int check_equiv(); -/* espresso.c */ extern pcover espresso(); -/* essen.c */ extern bool essen_cube(); -/* essen.c */ extern pcover cb_consensus(); -/* essen.c */ extern pcover cb_consensus_dist0(); -/* essen.c */ extern pcover essential(); -/* exact.c */ extern pcover minimize_exact(); -/* exact.c */ extern pcover minimize_exact_literals(); -/* expand.c */ extern bool feasibly_covered(); -/* expand.c */ extern int most_frequent(); -/* expand.c */ extern pcover all_primes(); -/* expand.c */ extern pcover expand(); -/* expand.c */ extern pcover find_all_primes(); -/* expand.c */ extern void elim_lowering(); -/* expand.c */ extern void essen_parts(); -/* expand.c */ extern void essen_raising(); -/* expand.c */ extern void expand1(); -/* expand.c */ extern void mincov(); -/* expand.c */ extern void select_feasible(); -/* expand.c */ extern void setup_BB_CC(); -/* gasp.c */ extern pcover expand_gasp(); -/* gasp.c */ extern pcover irred_gasp(); -/* gasp.c */ extern pcover last_gasp(); -/* gasp.c */ extern pcover super_gasp(); -/* gasp.c */ extern void expand1_gasp(); -/* getopt.c */ extern int getopt(); -/* hack.c */ extern find_dc_inputs(); -/* hack.c */ extern find_inputs(); -/* hack.c */ extern form_bitvector(); -/* hack.c */ extern map_dcset(); -/* hack.c */ extern map_output_symbolic(); -/* hack.c */ extern map_symbolic(); -/* hack.c */ extern pcover map_symbolic_cover(); -/* hack.c */ extern symbolic_hack_labels(); -/* irred.c */ extern bool cube_is_covered(); -/* irred.c */ extern bool taut_special_cases(); -/* irred.c */ extern bool tautology(); -/* irred.c */ extern pcover irredundant(); -/* irred.c */ extern void mark_irredundant(); -/* irred.c */ extern void irred_split_cover(); -/* irred.c */ extern sm_matrix *irred_derive_table(); -/* map.c */ extern pset minterms(); -/* map.c */ extern void explode(); -/* map.c */ extern void map(); -/* opo.c */ extern output_phase_setup(); -/* opo.c */ extern pPLA set_phase(); -/* opo.c */ extern pcover opo(); -/* opo.c */ extern pcube find_phase(); -/* opo.c */ extern pset_family find_covers(); -/* opo.c */ extern pset_family form_cover_table(); -/* opo.c */ extern pset_family opo_leaf(); -/* opo.c */ extern pset_family opo_recur(); -/* opo.c */ extern void opoall(); -/* opo.c */ extern void phase_assignment(); -/* opo.c */ extern void repeated_phase_assignment(); -/* pair.c */ extern generate_all_pairs(); -/* pair.c */ extern int **find_pairing_cost(); -/* pair.c */ extern int find_best_cost(); -/* pair.c */ extern int greedy_best_cost(); -/* pair.c */ extern int minimize_pair(); -/* pair.c */ extern int pair_free(); -/* pair.c */ extern pair_all(); -/* pair.c */ extern pcover delvar(); -/* pair.c */ extern pcover pairvar(); -/* pair.c */ extern ppair pair_best_cost(); -/* pair.c */ extern ppair pair_new(); -/* pair.c */ extern ppair pair_save(); -/* pair.c */ extern print_pair(); -/* pair.c */ extern void find_optimal_pairing(); -/* pair.c */ extern void set_pair(); -/* pair.c */ extern void set_pair1(); -/* primes.c */ extern pcover primes_consensus(); -/* reduce.c */ extern bool sccc_special_cases(); -/* reduce.c */ extern pcover reduce(); -/* reduce.c */ extern pcube reduce_cube(); -/* reduce.c */ extern pcube sccc(); -/* reduce.c */ extern pcube sccc_cube(); -/* reduce.c */ extern pcube sccc_merge(); -/* set.c */ extern bool set_andp(); -/* set.c */ extern bool set_orp(); -/* set.c */ extern bool setp_disjoint(); -/* set.c */ extern bool setp_empty(); -/* set.c */ extern bool setp_equal(); -/* set.c */ extern bool setp_full(); -/* set.c */ extern bool setp_implies(); -/* set.c */ extern char *pbv1(); -/* set.c */ extern char *ps1(); -/* set.c */ extern int *sf_count(); -/* set.c */ extern int *sf_count_restricted(); -/* set.c */ extern int bit_index(); -/* set.c */ extern int set_dist(); -/* set.c */ extern int set_ord(); -/* set.c */ extern void set_adjcnt(); -/* set.c */ extern pset set_and(); -/* set.c */ extern pset set_clear(); -/* set.c */ extern pset set_copy(); -/* set.c */ extern pset set_diff(); -/* set.c */ extern pset set_fill(); -/* set.c */ extern pset set_merge(); -/* set.c */ extern pset set_or(); -/* set.c */ extern pset set_xor(); -/* set.c */ extern pset sf_and(); -/* set.c */ extern pset sf_or(); -/* set.c */ extern pset_family sf_active(); -/* set.c */ extern pset_family sf_addcol(); -/* set.c */ extern pset_family sf_addset(); -/* set.c */ extern pset_family sf_append(); -/* set.c */ extern pset_family sf_bm_read(); -/* set.c */ extern pset_family sf_compress(); -/* set.c */ extern pset_family sf_copy(); -/* set.c */ extern pset_family sf_copy_col(); -/* set.c */ extern pset_family sf_delc(); -/* set.c */ extern pset_family sf_delcol(); -/* set.c */ extern pset_family sf_inactive(); -/* set.c */ extern pset_family sf_join(); -/* set.c */ extern pset_family sf_new(); -/* set.c */ extern pset_family sf_permute(); -/* set.c */ extern pset_family sf_read(); -/* set.c */ extern pset_family sf_save(); -/* set.c */ extern pset_family sf_transpose(); -/* set.c */ extern void set_write(); -/* set.c */ extern void sf_bm_print(); -/* set.c */ extern void sf_cleanup(); -/* set.c */ extern void sf_delset(); -/* set.c */ extern void sf_free(); -/* set.c */ extern void sf_print(); -/* set.c */ extern void sf_write(); -/* setc.c */ extern bool ccommon(); -/* setc.c */ extern bool cdist0(); -/* setc.c */ extern bool full_row(); -/* setc.c */ extern int ascend(); -/* setc.c */ extern int cactive(); -/* setc.c */ extern int cdist(); -/* setc.c */ extern int cdist01(); -/* setc.c */ extern int cvolume(); -/* setc.c */ extern int d1_order(); -/* setc.c */ extern int d1_order_size(); -/* setc.c */ extern int desc1(); -/* setc.c */ extern int descend(); -/* setc.c */ extern int lex_order(); -/* setc.c */ extern int lex_order1(); -/* setc.c */ extern pset force_lower(); -/* setc.c */ extern void consensus(); -/* sharp.c */ extern pcover cb1_dsharp(); -/* sharp.c */ extern pcover cb_dsharp(); -/* sharp.c */ extern pcover cb_recur_dsharp(); -/* sharp.c */ extern pcover cb_recur_sharp(); -/* sharp.c */ extern pcover cb_sharp(); -/* sharp.c */ extern pcover cv_dsharp(); -/* sharp.c */ extern pcover cv_intersect(); -/* sharp.c */ extern pcover cv_sharp(); -/* sharp.c */ extern pcover dsharp(); -/* sharp.c */ extern pcover make_disjoint(); -/* sharp.c */ extern pcover sharp(); -/* sminterf.c */pset do_sm_minimum_cover(); -/* sparse.c */ extern pcover make_sparse(); -/* sparse.c */ extern pcover mv_reduce(); -/* ucbqsort.c extern qsort(); */ -/* ucbqsort.c */ extern qst(); -/* unate.c */ extern pcover find_all_minimal_covers_petrick(); -/* unate.c */ extern pcover map_cover_to_unate(); -/* unate.c */ extern pcover map_unate_to_cover(); -/* unate.c */ extern pset_family exact_minimum_cover(); -/* unate.c */ extern pset_family gen_primes(); -/* unate.c */ extern pset_family unate_compl(); -/* unate.c */ extern pset_family unate_complement(); -/* unate.c */ extern pset_family unate_intersect(); -/* verify.c */ extern PLA_permute(); -/* verify.c */ extern bool PLA_verify(); -/* verify.c */ extern bool check_consistency(); -/* verify.c */ extern bool verify(); diff --git a/src/benchmarks/espresso/essen.c b/src/benchmarks/espresso/essen.c deleted file mode 100644 index 52a1655..0000000 --- a/src/benchmarks/espresso/essen.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - module: essen.c - purpose: Find essential primes in a multiple-valued function -*/ - -#include "espresso.h" - -/* - essential -- return a cover consisting of the cubes of F which are - essential prime implicants (with respect to F u D); Further, remove - these cubes from the ON-set F, and add them to the OFF-set D. - - Sometimes EXPAND can determine that a cube is not an essential prime. - If so, it will set the "NONESSEN" flag in the cube. - - We count on IRREDUNDANT to have set the flag RELESSEN to indicate - that a prime was relatively essential (i.e., covers some minterm - not contained in any other prime in the current cover), or to have - reset the flag to indicate that a prime was relatively redundant - (i.e., all minterms covered by other primes in the current cover). - Of course, after executing irredundant, all of the primes in the - cover are relatively essential, but we can mark the primes which - were redundant at the start of irredundant and avoid an extra check - on these primes for essentiality. -*/ - -pcover essential(Fp, Dp) -IN pcover *Fp, *Dp; -{ - register pcube last, p; - pcover E, F = *Fp, D = *Dp; - - /* set all cubes in F active */ - (void) sf_active(F); - - /* Might as well start out with some cubes in E */ - E = new_cover(10); - - foreach_set(F, last, p) { - /* don't test a prime which EXPAND says is nonessential */ - if (! TESTP(p, NONESSEN)) { - /* only test a prime which was relatively essential */ - if (TESTP(p, RELESSEN)) { - /* Check essentiality */ - if (essen_cube(F, D, p)) { - if (debug & ESSEN) - printf("ESSENTIAL: %s\n", pc1(p)); - E = sf_addset(E, p); - RESET(p, ACTIVE); - F->active_count--; - } - } - } - } - - *Fp = sf_inactive(F); /* delete the inactive cubes from F */ - *Dp = sf_join(D, E); /* add the essentials to D */ - sf_free(D); - return E; -} - -/* - essen_cube -- check if a single cube is essential or not - - The prime c is essential iff - - consensus((F u D) # c, c) u D - - does not contain c. -*/ -bool essen_cube(F, D, c) -IN pcover F, D; -IN pcube c; -{ - pcover H, FD; - pcube *H1; - bool essen; - - /* Append F and D together, and take the sharp-consensus with c */ - FD = sf_join(F, D); - H = cb_consensus(FD, c); - free_cover(FD); - - /* Add the don't care set, and see if this covers c */ - H1 = cube2list(H, D); - essen = ! cube_is_covered(H1, c); - free_cubelist(H1); - - free_cover(H); - return essen; -} - - -/* - * cb_consensus -- compute consensus(T # c, c) - */ -pcover cb_consensus(T, c) -register pcover T; -register pcube c; -{ - register pcube temp, last, p; - register pcover R; - - R = new_cover(T->count*2); - temp = new_cube(); - foreach_set(T, last, p) { - if (p != c) { - switch (cdist01(p, c)) { - case 0: - /* distance-0 needs special care */ - R = cb_consensus_dist0(R, p, c); - break; - - case 1: - /* distance-1 is easy because no sharping required */ - consensus(temp, p, c); - R = sf_addset(R, temp); - break; - } - } - } - set_free(temp); - return R; -} - - -/* - * form the sharp-consensus for p and c when they intersect - * What we are forming is consensus(p # c, c). - */ -pcover cb_consensus_dist0(R, p, c) -pcover R; -register pcube p, c; -{ - int var; - bool got_one; - register pcube temp, mask; - register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1]; - - /* If c contains p, then this gives us no information for essential test */ - if (setp_implies(p, c)) { - return R; - } - - /* For the multiple-valued variables */ - temp = new_cube(); - got_one = FALSE; - INLINEset_diff(p_diff_c, p, c); - INLINEset_and(p_and_c, p, c); - - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - /* Check if c(var) is contained in p(var) -- if so, no news */ - mask = cube.var_mask[var]; - if (! setp_disjoint(p_diff_c, mask)) { - INLINEset_merge(temp, c, p_and_c, mask); - R = sf_addset(R, temp); - got_one = TRUE; - } - } - - /* if no cube so far, add one for the intersection */ - if (! got_one && cube.num_binary_vars > 0) { - /* Add a single cube for the intersection of p and c */ - INLINEset_and(temp, p, c); - R = sf_addset(R, temp); - } - - set_free(temp); - return R; -} diff --git a/src/benchmarks/espresso/exact.c b/src/benchmarks/espresso/exact.c deleted file mode 100644 index 336a3ff..0000000 --- a/src/benchmarks/espresso/exact.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "espresso.h" -#include <stdio.h> - -static void dump_irredundant(); -static pcover do_minimize(); - - -/* - * minimize_exact -- main entry point for exact minimization - * - * Global flags which affect this routine are: - * - * debug - * skip_make_sparse - */ - -pcover -minimize_exact(F, D, R, exact_cover) -pcover F, D, R; -int exact_cover; -{ - return do_minimize(F, D, R, exact_cover, /*weighted*/ 0); -} - - -pcover -minimize_exact_literals(F, D, R, exact_cover) -pcover F, D, R; -int exact_cover; -{ - return do_minimize(F, D, R, exact_cover, /*weighted*/ 1); -} - - - -static pcover -do_minimize(F, D, R, exact_cover, weighted) -pcover F, D, R; -int exact_cover; -int weighted; -{ - pcover newF, E, Rt, Rp; - pset p, last; - int heur, level, *weights; - sm_matrix *table; - sm_row *cover; - sm_element *pe; - int debug_save = debug; - - if (debug & EXACT) { - debug |= (IRRED | MINCOV); - } -#if defined(sun) || defined(bsd4_2) /* hack ... */ - if (debug & MINCOV) { -// setlinebuf(stdout); - } -#endif - level = (debug & MINCOV) ? 4 : 0; - heur = ! exact_cover; - - /* Generate all prime implicants */ - EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F); - - /* Setup the prime implicant table */ - EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E); - EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp); - - /* Solve either a weighted or nonweighted covering problem */ - if (weighted) { - /* correct only for all 2-valued variables */ - weights = ALLOC(int, F->count); - foreach_set(Rp, last, p) { - weights[SIZE(p)] = cube.size - set_ord(p); - } - } else { - weights = NIL(int); - } - EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F); - if (weights != 0) { - FREE(weights); - } - - if (debug & EXACT) { - dump_irredundant(E, Rt, Rp, table); - } - - /* Form the result cover */ - newF = new_cover(100); - foreach_set(E, last, p) { - newF = sf_addset(newF, p); - } - sm_foreach_row_element(cover, pe) { - newF = sf_addset(newF, GETSET(F, pe->col_num)); - } - - free_cover(E); - free_cover(Rt); - free_cover(Rp); - sm_free(table); - sm_row_free(cover); - free_cover(F); - - /* Attempt to make the results more sparse */ - debug &= ~ (IRRED | SHARP | MINCOV); - if (! skip_make_sparse && R != 0) { - newF = make_sparse(newF, D, R); - } - - debug = debug_save; - return newF; -} - -static void -dump_irredundant(E, Rt, Rp, table) -pcover E, Rt, Rp; -sm_matrix *table; -{ - FILE *fp_pi_table, *fp_primes; - pPLA PLA; - pset last, p; - char *file; - - if (filename == 0 || strcmp(filename, "(stdin)") == 0) { - fp_pi_table = fp_primes = stdout; - } else { - file = ALLOC(char, strlen(filename)+20); - (void) sprintf(file, "%s.primes", filename); - if ((fp_primes = fopen(file, "w")) == NULL) { - fprintf(stderr, "espresso: Unable to open %s\n", file); - fp_primes = stdout; - } - (void) sprintf(file, "%s.pi", filename); - if ((fp_pi_table = fopen(file, "w")) == NULL) { - fprintf(stderr, "espresso: Unable to open %s\n", file); - fp_pi_table = stdout; - } - FREE(file); - } - - PLA = new_PLA(); - PLA_labels(PLA); - - fpr_header(fp_primes, PLA, F_type); - free_PLA(PLA); - - (void) fprintf(fp_primes, "# Essential primes are\n"); - foreach_set(E, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - fprintf(fp_primes, "# Totally redundant primes are\n"); - foreach_set(Rt, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - fprintf(fp_primes, "# Partially redundant primes are\n"); - foreach_set(Rp, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - if (fp_primes != stdout) { - (void) fclose(fp_primes); - } - - sm_write(fp_pi_table, table); - if (fp_pi_table != stdout) { - (void) fclose(fp_pi_table); - } -} diff --git a/src/benchmarks/espresso/expand.c b/src/benchmarks/espresso/expand.c deleted file mode 100644 index 8eb7239..0000000 --- a/src/benchmarks/espresso/expand.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - module: expand.c - purpose: Perform the Espresso-II Expansion Step - - The idea is to take each nonprime cube of the on-set and expand it - into a prime implicant such that we can cover as many other cubes - of the on-set. If no cube of the on-set can be covered, then we - expand each cube into a large prime implicant by transforming the - problem into a minimum covering problem which is solved by the - heuristics of minimum_cover. - - These routines revolve around having a representation of the - OFF-set. (In contrast to the Espresso-II manuscript, we do NOT - require an "unwrapped" version of the OFF-set). - - Some conventions on variable names: - - SUPER_CUBE is the supercube of all cubes which can be covered - by an expansion of the cube being expanded - - OVEREXPANDED_CUBE is the cube which would result from expanding - all parts which can expand individually of the cube being expanded - - RAISE is the current expansion of the current cube - - FREESET is the set of parts which haven't been raised or lowered yet. - - INIT_LOWER is a set of parts to be removed from the free parts before - starting the expansion -*/ - -#include "espresso.h" - -/* - expand -- expand each nonprime cube of F into a prime implicant - - If nonsparse is true, only the non-sparse variables will be expanded; - this is done by forcing all of the sparse variables out of the free set. -*/ - -pcover expand(F, R, nonsparse) -INOUT pcover F; -IN pcover R; -IN bool nonsparse; /* expand non-sparse variables only */ -{ - register pcube last, p; - pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE; - int var, num_covered; - bool change; - - /* Order the cubes according to "chewing-away from the edges" of mini */ - if (use_random_order) - F = random_order(F); - else - F = mini_sort(F, ascend); - - /* Allocate memory for variables needed by expand1() */ - RAISE = new_cube(); - FREESET = new_cube(); - INIT_LOWER = new_cube(); - SUPER_CUBE = new_cube(); - OVEREXPANDED_CUBE = new_cube(); - - /* Setup the initial lowering set (differs only for nonsparse) */ - if (nonsparse) - for(var = 0; var < cube.num_vars; var++) - if (cube.sparse[var]) - (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]); - - /* Mark all cubes as not covered, and maybe essential */ - foreach_set(F, last, p) { - RESET(p, COVERED); - RESET(p, NONESSEN); - } - - /* Try to expand each nonprime and noncovered cube */ - foreach_set(F, last, p) { - /* do not expand if PRIME or if covered by previous expansion */ - if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) { - - /* expand the cube p, result is RAISE */ - expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, - INIT_LOWER, &num_covered, p); - if (debug & EXPAND) - printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered); - (void) set_copy(p, RAISE); - SET(p, PRIME); - RESET(p, COVERED); /* not really necessary */ - - /* See if we generated an inessential prime */ - if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) { - SET(p, NONESSEN); - } - } - } - - /* Delete any cubes of F which became covered during the expansion */ - F->active_count = 0; - change = FALSE; - foreach_set(F, last, p) { - if (TESTP(p, COVERED)) { - RESET(p, ACTIVE); - change = TRUE; - } else { - SET(p, ACTIVE); - F->active_count++; - } - } - if (change) - F = sf_inactive(F); - - free_cube(RAISE); - free_cube(FREESET); - free_cube(INIT_LOWER); - free_cube(SUPER_CUBE); - free_cube(OVEREXPANDED_CUBE); - return F; -} - -/* - expand1 -- Expand a single cube against the OFF-set -*/ -void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, - INIT_LOWER, num_covered, c) -pcover BB; /* Blocking matrix (OFF-set) */ -pcover CC; /* Covering matrix (ON-set) */ -pcube RAISE; /* The current parts which have been raised */ -pcube FREESET; /* The current parts which are free */ -pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */ -pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */ -pcube INIT_LOWER; /* Parts to initially remove from FREESET */ -int *num_covered; /* Number of cubes of CC which are covered */ -pcube c; /* The cube to be expanded */ -{ - int bestindex; - - if (debug & EXPAND1) - printf("\nEXPAND1: \t%s\n", pc1(c)); - - /* initialize BB and CC */ - SET(c, PRIME); /* don't try to cover ourself */ - setup_BB_CC(BB, CC); - - /* initialize count of # cubes covered, and the supercube of them */ - *num_covered = 0; - (void) set_copy(SUPER_CUBE, c); - - /* Initialize the lowering, raising and unassigned sets */ - (void) set_copy(RAISE, c); - (void) set_diff(FREESET, cube.fullset, RAISE); - - /* If some parts are forced into lowering set, remove them */ - if (! setp_empty(INIT_LOWER)) { - (void) set_diff(FREESET, FREESET, INIT_LOWER); - elim_lowering(BB, CC, RAISE, FREESET); - } - - /* Determine what can be raised, and return the over-expanded cube */ - essen_parts(BB, CC, RAISE, FREESET); - (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET); - - /* While there are still cubes which can be covered, cover them ! */ - if (CC->active_count > 0) { - select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered); - } - - /* While there are still cubes covered by the overexpanded cube ... */ - while (CC->active_count > 0) { - bestindex = most_frequent(CC, FREESET); - set_insert(RAISE, bestindex); - set_remove(FREESET, bestindex); - essen_parts(BB, CC, RAISE, FREESET); - } - - /* Finally, when all else fails, choose the largest possible prime */ - /* We will loop only if we decide unravelling OFF-set is too expensive */ - while (BB->active_count > 0) { - mincov(BB, RAISE, FREESET); - } - - /* Raise any remaining free coordinates */ - (void) set_or(RAISE, RAISE, FREESET); -} - -/* - essen_parts -- determine which parts are forced into the lowering - set to insure that the cube be orthognal to the OFF-set. - - If any cube of the OFF-set is distance 1 from the raising cube, - then we must lower all parts of the conflicting variable. (If the - cube is distance 0, we detect this error here.) - - If there are essentially lowered parts, we can remove from consideration - any cubes of the OFF-set which are more than distance 1 from the - overexpanded cube of RAISE. -*/ - -void essen_parts(BB, CC, RAISE, FREESET) -pcover BB, CC; -pcube RAISE, FREESET; -{ - register pcube p, r = RAISE; - pcube lastp, xlower = cube.temp[0]; - int dist; - - (void) set_copy(xlower, cube.emptyset); - - foreach_active_set(BB, lastp, p) { -#ifdef NO_INLINE - if ((dist = cdist01(p, r)) > 1) goto exit_if; -#else - {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) -{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto -exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||( -dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube -mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[ -var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[ -w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}} -#endif - if (dist == 0) { - fatal("ON-set and OFF-set are not orthogonal"); - } else { - (void) force_lower(xlower, p, r); - BB->active_count--; - RESET(p, ACTIVE); - } -exit_if: ; - } - - if (! setp_empty(xlower)) { - (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */ - elim_lowering(BB, CC, RAISE, FREESET); - } - - if (debug & EXPAND1) - printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); -} - -/* - essen_raising -- determine which parts may always be added to - the raising set without restricting further expansions - - General rule: if some part is not blocked by any cube of BB, then - this part can always be raised. -*/ - -void essen_raising(BB, RAISE, FREESET) -register pcover BB; -pcube RAISE, FREESET; -{ - register pcube last, p, xraise = cube.temp[0]; - - /* Form union of all cubes of BB, and then take complement wrt FREESET */ - (void) set_copy(xraise, cube.emptyset); - foreach_active_set(BB, last, p) - INLINEset_or(xraise, xraise, p); - (void) set_diff(xraise, FREESET, xraise); - - (void) set_or(RAISE, RAISE, xraise); /* add to raising set */ - (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */ - - if (debug & EXPAND1) - printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n", - pc1(RAISE), pc2(FREESET)); -} - -/* - elim_lowering -- after removing parts from FREESET, we can reduce the - size of both BB and CC. - - We mark as inactive any cube of BB which does not intersect the - overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove - from CC any cube which is not covered by the overexpanded cube. -*/ - -void elim_lowering(BB, CC, RAISE, FREESET) -pcover BB, CC; -pcube RAISE, FREESET; -{ - register pcube p, r = set_or(cube.temp[0], RAISE, FREESET); - pcube last; - - /* - * Remove sets of BB which are orthogonal to future expansions - */ - foreach_active_set(BB, last, p) { -#ifdef NO_INLINE - if (! cdist0(p, r)) -#else - {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[ -lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto lfalse;for(w=1;w<lastw;w++){x=p[w] -&r[w];if(~(x|x>>1)&DISJOINT)goto lfalse;}}}{register int w,var,lastw;register -pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube. -var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++) -if(p[w]&r[w]&mask[w])goto nextvar;goto lfalse;nextvar:;}}continue;lfalse: -#endif - BB->active_count--, RESET(p, ACTIVE); - } - - - /* - * Remove sets of CC which cannot be covered by future expansions - */ - if (CC != (pcover) NULL) { - foreach_active_set(CC, last, p) { -#ifdef NO_INLINE - if (! setp_implies(p, r)) -#else - INLINEsetp_implies(p, r, /* when false => */ goto false1); - /* when true => go to end of loop */ continue; - false1: -#endif - CC->active_count--, RESET(p, ACTIVE); - } - } -} - -/* - most_frequent -- When all else fails, select a reasonable part to raise - The active cubes of CC are the cubes which are covered by the - overexpanded cube of the original cube (however, we know that none - of them can actually be covered by a feasible expansion of the - original cube). We resort to the MINI strategy of selecting to - raise the part which will cover the same part in the most cubes of CC. -*/ -int most_frequent(CC, FREESET) -pcover CC; -pcube FREESET; -{ - register int i, best_part, best_count, *count; - register pset p, last; - - /* Count occurences of each variable */ - count = ALLOC(int, cube.size); - for(i = 0; i < cube.size; i++) - count[i] = 0; - if (CC != (pcover) NULL) - foreach_active_set(CC, last, p) - set_adjcnt(p, count, 1); - - /* Now find which free part occurs most often */ - best_count = best_part = -1; - for(i = 0; i < cube.size; i++) - if (is_in_set(FREESET,i) && count[i] > best_count) { - best_part = i; - best_count = count[i]; - } - FREE(count); - - if (debug & EXPAND1) - printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET)); - return best_part; -} - -/* - setup_BB_CC -- set up the blocking and covering set families; - - Note that the blocking family is merely the set of cubes of R, and - that CC is the set of cubes of F which might possibly be covered - (i.e., nonprime cubes, and cubes not already covered) -*/ - -void setup_BB_CC(BB, CC) -register pcover BB, CC; -{ - register pcube p, last; - - /* Create the block and cover set families */ - BB->active_count = BB->count; - foreach_set(BB, last, p) - SET(p, ACTIVE); - - if (CC != (pcover) NULL) { - CC->active_count = CC->count; - foreach_set(CC, last, p) - if (TESTP(p, COVERED) || TESTP(p, PRIME)) - CC->active_count--, RESET(p, ACTIVE); - else - SET(p, ACTIVE); - } -} - -/* - select_feasible -- Determine if there are cubes which can be covered, - and if so, raise those parts necessary to cover as many as possible. - - We really don't check to maximize the number that can be covered; - instead, we check, for each fcc, how many other fcc remain fcc - after expanding to cover the fcc. (Essentially one-level lookahead). -*/ - -void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered) -pcover BB, CC; -pcube RAISE, FREESET, SUPER_CUBE; -int *num_covered; -{ - register pcube p, last, bestfeas, *feas; - register int i, j; - pcube *feas_new_lower; - int bestcount, bestsize, count, size, numfeas, lastfeas; - pcover new_lower; - - /* Start out with all cubes covered by the over-expanded cube as - * the "possibly" feasibly-covered cubes (pfcc) - */ - feas = ALLOC(pcube, CC->active_count); - numfeas = 0; - foreach_active_set(CC, last, p) - feas[numfeas++] = p; - - /* Setup extra cubes to record parts forced low after a covering */ - feas_new_lower = ALLOC(pcube, CC->active_count); - new_lower = new_cover(numfeas); - for(i = 0; i < numfeas; i++) - feas_new_lower[i] = GETSET(new_lower, i); - - -loop: - /* Find the essentially raised parts -- this might cover some cubes - for us, without having to find out if they are fcc or not - */ - essen_raising(BB, RAISE, FREESET); - - /* Now check all "possibly" feasibly covered cubes to check feasibility */ - lastfeas = numfeas; - numfeas = 0; - for(i = 0; i < lastfeas; i++) { - p = feas[i]; - - /* Check active because essen_parts might have removed it */ - if (TESTP(p, ACTIVE)) { - - /* See if the cube is already covered by RAISE -- - * this can happen because of essen_raising() or because of - * the previous "loop" - */ - if (setp_implies(p, RAISE)) { - (*num_covered) += 1; - (void) set_or(SUPER_CUBE, SUPER_CUBE, p); - CC->active_count--; - RESET(p, ACTIVE); - SET(p, COVERED); - /* otherwise, test if it is feasibly covered */ - } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) { - feas[numfeas] = p; /* save the fcc */ - numfeas++; - } - } - } - if (debug & EXPAND1) - printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n", - lastfeas, numfeas); - - /* Exit here if there are no feasibly covered cubes */ - if (numfeas == 0) { - FREE(feas); - FREE(feas_new_lower); - free_cover(new_lower); - return; - } - - /* Now find which is the best feasibly covered cube */ - bestcount = 0; - bestsize = 9999; - for(i = 0; i < numfeas; i++) { - size = set_dist(feas[i], FREESET); /* # of newly raised parts */ - count = 0; /* # of other cubes which remain fcc after raising */ - -#define NEW -#ifdef NEW - for(j = 0; j < numfeas; j++) - if (setp_disjoint(feas_new_lower[i], feas[j])) - count++; -#else - for(j = 0; j < numfeas; j++) - if (setp_implies(feas[j], feas[i])) - count++; -#endif - if (count > bestcount) { - bestcount = count; - bestfeas = feas[i]; - bestsize = size; - } else if (count == bestcount && size < bestsize) { - bestfeas = feas[i]; - bestsize = size; - } - } - - /* Add the necessary parts to the raising set */ - (void) set_or(RAISE, RAISE, bestfeas); - (void) set_diff(FREESET, FREESET, RAISE); - if (debug & EXPAND1) - printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); - essen_parts(BB, CC, RAISE, FREESET); - goto loop; -/* NOTREACHED */ -} - -/* - feasibly_covered -- determine if the cube c is feasibly covered - (i.e., if it is possible to raise all of the necessary variables - while still insuring orthogonality with R). Also, if c is feasibly - covered, then compute the new set of parts which are forced into - the lowering set. -*/ - -bool feasibly_covered(BB, c, RAISE, new_lower) -pcover BB; -pcube c, RAISE, new_lower; -{ - register pcube p, r = set_or(cube.temp[0], RAISE, c); - int dist; - pcube lastp; - - set_copy(new_lower, cube.emptyset); - foreach_active_set(BB, lastp, p) { -#ifdef NO_INLINE - if ((dist = cdist01(p, r)) > 1) goto exit_if; -#else - {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) -{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto -exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||( -dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube -mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[ -var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[ -w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}} -#endif - if (dist == 0) - return FALSE; - else - (void) force_lower(new_lower, p, r); - exit_if: ; - } - return TRUE; -} - -/* - mincov -- transform the problem of expanding a cube to a maximally- - large prime implicant into the problem of selecting a minimum - cardinality cover over a family of sets. - - When we get to this point, we must unravel the remaining off-set. - This may be painful. -*/ - -void mincov(BB, RAISE, FREESET) -pcover BB; -pcube RAISE, FREESET; -{ - int expansion, nset, var, dist; - pset_family B; - register pcube xraise=cube.temp[0], xlower, p, last, plower; - -#ifdef RANDOM_MINCOV - dist = random() % set_ord(FREESET); - for(var = 0; var < cube.size && dist >= 0; var++) { - if (is_in_set(FREESET, var)) { - dist--; - } - } - - set_insert(RAISE, var); - set_remove(FREESET, var); - (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); -#else - - /* Create B which are those cubes which we must avoid intersecting */ - B = new_cover(BB->active_count); - foreach_active_set(BB, last, p) { - plower = set_copy(GETSET(B, B->count++), cube.emptyset); - (void) force_lower(plower, p, RAISE); - } - - /* Determine how many sets it will blow up into after the unravel */ - nset = 0; - foreach_set(B, last, p) { - expansion = 1; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - if ((dist=set_dist(p, cube.var_mask[var])) > 1) { - expansion *= dist; - if (expansion > 500) goto heuristic_mincov; - } - } - nset += expansion; - if (nset > 500) goto heuristic_mincov; - } - - B = unravel(B, cube.num_binary_vars); - xlower = do_sm_minimum_cover(B); - - /* Add any remaining free parts to the raising set */ - (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower)); - (void) set_copy(FREESET, cube.emptyset); /* free set is empty */ - BB->active_count = 0; /* BB satisfied */ - if (debug & EXPAND1) { - printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); - } - sf_free(B); - set_free(xlower); - return; - -heuristic_mincov: - sf_free(B); - /* most_frequent will pick first free part */ - set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET)); - (void) set_diff(FREESET, FREESET, RAISE); - essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); - return; -#endif -} - -/* - find_all_primes -- find all of the primes which cover the - currently reduced BB -*/ -pcover find_all_primes(BB, RAISE, FREESET) -pcover BB; -register pcube RAISE, FREESET; -{ - register pset last, p, plower; - pset_family B, B1; - - if (BB->active_count == 0) { - B1 = new_cover(1); - p = GETSET(B1, B1->count++); - (void) set_copy(p, RAISE); - SET(p, PRIME); - } else { - B = new_cover(BB->active_count); - foreach_active_set(BB, last, p) { - plower = set_copy(GETSET(B, B->count++), cube.emptyset); - (void) force_lower(plower, p, RAISE); - } - B = sf_rev_contain(unravel(B, cube.num_binary_vars)); - B1 = exact_minimum_cover(B); - foreach_set(B1, last, p) { - INLINEset_diff(p, FREESET, p); - INLINEset_or(p, p, RAISE); - SET(p, PRIME); - } - free_cover(B); - } - return B1; -} - -/* - all_primes -- foreach cube in F, generate all of the primes - which cover the cube. -*/ - -pcover all_primes(F, R) -pcover F, R; -{ - register pcube last, p, RAISE, FREESET; - pcover Fall_primes, B1; - - FREESET = new_cube(); - RAISE = new_cube(); - Fall_primes = new_cover(F->count); - - foreach_set(F, last, p) { - if (TESTP(p, PRIME)) { - Fall_primes = sf_addset(Fall_primes, p); - } else { - /* Setup for call to essential parts */ - (void) set_copy(RAISE, p); - (void) set_diff(FREESET, cube.fullset, RAISE); - setup_BB_CC(R, /* CC */ (pcover) NULL); - essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET); - - /* Find all of the primes, and add them to the prime set */ - B1 = find_all_primes(R, RAISE, FREESET); - Fall_primes = sf_append(Fall_primes, B1); - } - } - - set_free(RAISE); - set_free(FREESET); - return Fall_primes; -} diff --git a/src/benchmarks/espresso/gasp.c b/src/benchmarks/espresso/gasp.c deleted file mode 100644 index b9a3d90..0000000 --- a/src/benchmarks/espresso/gasp.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - module: gasp.c - - The "last_gasp" heuristic computes the reduction of each cube in - the cover (without replacement) and then performs an expansion of - these cubes. The cubes which expand to cover some other cube are - added to the original cover and irredundant finds a minimal subset. - - If one of the reduced cubes expands to cover some other reduced - cube, then the new prime thus generated is a candidate for reducing - the size of the cover. - - super_gasp is a variation on this strategy which extracts a minimal - subset from the set of all prime implicants which cover all - maximally reduced cubes. -*/ - -#include "espresso.h" - - -/* - * reduce_gasp -- compute the maximal reduction of each cube of F - * - * If a cube does not reduce, it remains prime; otherwise, it is marked - * as nonprime. If the cube is redundant (should NEVER happen here) we - * just crap out ... - * - * A cover with all of the cubes of F is returned. Those that did - * reduce are marked "NONPRIME"; those that reduced are marked "PRIME". - * The cubes are in the same order as in F. - */ -static pcover reduce_gasp(F, D) -pcover F, D; -{ - pcube p, last, cunder, *FD; - pcover G; - - G = new_cover(F->count); - FD = cube2list(F, D); - - /* Reduce cubes of F without replacement */ - foreach_set(F, last, p) { - cunder = reduce_cube(FD, p); - if (setp_empty(cunder)) { - fatal("empty reduction in reduce_gasp, shouldn't happen"); - } else if (setp_equal(cunder, p)) { - SET(cunder, PRIME); /* just to make sure */ - G = sf_addset(G, p); /* it did not reduce ... */ - } else { - RESET(cunder, PRIME); /* it reduced ... */ - G = sf_addset(G, cunder); - } - if (debug & GASP) { - printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder)); - } - free_cube(cunder); - } - - free_cubelist(FD); - return G; -} - -/* - * expand_gasp -- expand each nonprime cube of F into a prime implicant - * - * The gasp strategy differs in that only those cubes which expand to - * cover some other cube are saved; also, all cubes are expanded - * regardless of whether they become covered or not. - */ - -pcover expand_gasp(F, D, R, Foriginal) -INOUT pcover F; -IN pcover D; -IN pcover R; -IN pcover Foriginal; -{ - int c1index; - pcover G; - - /* Try to expand each nonprime and noncovered cube */ - G = new_cover(10); - for(c1index = 0; c1index < F->count; c1index++) { - expand1_gasp(F, D, R, Foriginal, c1index, &G); - } - G = sf_dupl(G); - G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */ - return G; -} - - - -/* - * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy - */ -void expand1_gasp(F, D, R, Foriginal, c1index, G) -pcover F; /* reduced cubes of ON-set */ -pcover D; /* DC-set */ -pcover R; /* OFF-set */ -pcover Foriginal; /* ON-set before reduction (same order as F) */ -int c1index; /* which index of F (or Freduced) to be checked */ -pcover *G; -{ - register int c2index; - register pcube p, last, c2under; - pcube RAISE, FREESET, temp, *FD, c2essential; - pcover F1; - - if (debug & EXPAND1) { - printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index))); - } - - RAISE = new_cube(); - FREESET = new_cube(); - temp = new_cube(); - - /* Initialize the OFF-set */ - R->active_count = R->count; - foreach_set(R, last, p) { - SET(p, ACTIVE); - } - /* Initialize the reduced ON-set, all nonprime cubes become active */ - F->active_count = F->count; - foreachi_set(F, c2index, c2under) { - if (c1index == c2index || TESTP(c2under, PRIME)) { - F->active_count--; - RESET(c2under, ACTIVE); - } else { - SET(c2under, ACTIVE); - } - } - - /* Initialize the raising and unassigned sets */ - (void) set_copy(RAISE, GETSET(F, c1index)); - (void) set_diff(FREESET, cube.fullset, RAISE); - - /* Determine parts which must be lowered */ - essen_parts(R, F, RAISE, FREESET); - - /* Determine parts which can always be raised */ - essen_raising(R, RAISE, FREESET); - - /* See which, if any, of the reduced cubes we can cover */ - foreachi_set(F, c2index, c2under) { - if (TESTP(c2under, ACTIVE)) { - /* See if this cube can be covered by an expansion */ - if (setp_implies(c2under, RAISE) || - feasibly_covered(R, c2under, RAISE, temp)) { - - /* See if c1under can expanded to cover c2 reduced against - * (F - c1) u c1under; if so, c2 can definitely be removed ! - */ - - /* Copy F and replace c1 with c1under */ - F1 = sf_save(Foriginal); - (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index)); - - /* Reduce c2 against ((F - c1) u c1under) */ - FD = cube2list(F1, D); - c2essential = reduce_cube(FD, GETSET(F1, c2index)); - free_cubelist(FD); - sf_free(F1); - - /* See if c2essential is covered by an expansion of c1under */ - if (feasibly_covered(R, c2essential, RAISE, temp)) { - (void) set_or(temp, RAISE, c2essential); - RESET(temp, PRIME); /* cube not prime */ - *G = sf_addset(*G, temp); - } - set_free(c2essential); - } - } - } - - free_cube(RAISE); - free_cube(FREESET); - free_cube(temp); -} - -/* irred_gasp -- Add new primes to F and find an irredundant subset */ -pcover irred_gasp(F, D, G) -pcover F, D, G; /* G is disposed of */ -{ - if (G->count != 0) - F = irredundant(sf_append(F, G), D); - else - free_cover(G); - return F; -} - - -/* last_gasp */ -pcover last_gasp(F, D, R, cost) -pcover F, D, R; -cost_t *cost; -{ - pcover G, G1; - - EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); - EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost); - free_cover(G); - EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost); - return F; -} - - -/* super_gasp */ -pcover super_gasp(F, D, R, cost) -pcover F, D, R; -cost_t *cost; -{ - pcover G, G1; - - EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); - EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost); - free_cover(G); - EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G); - EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost); - return F; -} diff --git a/src/benchmarks/espresso/getopt.c b/src/benchmarks/espresso/getopt.c deleted file mode 100644 index 017c907..0000000 --- a/src/benchmarks/espresso/getopt.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "espresso.h" -#include "port.h" -/* File : getopt.c - Author : Henry Spencer, University of Toronto - Updated: 28 April 1984 - Purpose: get option letter from argv. -*/ -#define NullS ((char *) 0) - -char *optarg; /* Global argument pointer. */ -int optind = 0; /* Global argv index. */ - -int getopt(int argc, char * const * argv, const char * optstring) - { - register int c; - register char *place; - static char *scan = NullS; /* Private scan pointer. */ - - optarg = NullS; - - if (scan == NullS || *scan == '\0') { - if (optind == 0) optind++; - if (optind >= argc) return EOF; - place = argv[optind]; - if (place[0] != '-' || place[1] == '\0') return EOF; - optind++; - if (place[1] == '-' && place[2] == '\0') return EOF; - scan = place+1; - } - - c = *scan++; - place = strchr(optstring, c); - if (place == NullS || c == ':') { - fprintf(stderr, "%s: unknown option %c\n", argv[0], c); - return '?'; - } - if (*++place == ':') { - if (*scan != '\0') { - optarg = scan, scan = NullS; - } else { - optarg = argv[optind], optind++; - } - } - return c; - } diff --git a/src/benchmarks/espresso/gimpel.c b/src/benchmarks/espresso/gimpel.c deleted file mode 100644 index d1122b7..0000000 --- a/src/benchmarks/espresso/gimpel.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - - -/* - * check for: - * - * c1 c2 rest - * -- -- --- - * 1 1 0 0 0 0 <-- primary row - * 1 0 S1 <-- secondary row - * 0 1 T1 - * 0 1 T2 - * 0 1 Tn - * 0 0 R - */ - -int -gimpel_reduce(A, select, weight, lb, bound, depth, stats, best) -sm_matrix *A; -solution_t *select; -int *weight; -int lb; -int bound; -int depth; -stats_t *stats; -solution_t **best; -{ - register sm_row *prow, *save_sec; - register sm_col *c1, *c2; - register sm_element *p, *p1; - int c1_col_num, c2_col_num, primary_row_num, secondary_row_num; - int reduce_it; - - reduce_it = 0; - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->length == 2) { - c1 = sm_get_col(A, prow->first_col->col_num); - c2 = sm_get_col(A, prow->last_col->col_num); - if (c1->length == 2) { - reduce_it = 1; - } else if (c2->length == 2) { - c1 = sm_get_col(A, prow->last_col->col_num); - c2 = sm_get_col(A, prow->first_col->col_num); - reduce_it = 1; - } - if (reduce_it) { - primary_row_num = prow->row_num; - secondary_row_num = c1->first_row->row_num; - if (secondary_row_num == primary_row_num) { - secondary_row_num = c1->last_row->row_num; - } - break; - } - } - } - - if (reduce_it) { - c1_col_num = c1->col_num; - c2_col_num = c2->col_num; - save_sec = sm_row_dup(sm_get_row(A, secondary_row_num)); - sm_row_remove(save_sec, c1_col_num); - - for(p = c2->first_row; p != 0; p = p->next_row) { - if (p->row_num != primary_row_num) { - /* merge rows S1 and T */ - for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) { - (void) sm_insert(A, p->row_num, p1->col_num); - } - } - } - - sm_delcol(A, c1_col_num); - sm_delcol(A, c2_col_num); - sm_delrow(A, primary_row_num); - sm_delrow(A, secondary_row_num); - - stats->gimpel_count++; - stats->gimpel++; - *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats); - stats->gimpel--; - - if (*best != NIL(solution_t)) { - /* is secondary row covered ? */ - if (sm_row_intersects(save_sec, (*best)->row)) { - /* yes, actually select c2 */ - solution_add(*best, weight, c2_col_num); - } else { - solution_add(*best, weight, c1_col_num); - } - } - - sm_row_free(save_sec); - return 1; - } else { - return 0; - } -} diff --git a/src/benchmarks/espresso/globals.c b/src/benchmarks/espresso/globals.c deleted file mode 100644 index dc0b958..0000000 --- a/src/benchmarks/espresso/globals.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "espresso.h" - -/* - * Global Variable Declarations - */ - -unsigned int debug; /* debug parameter */ -bool verbose_debug; /* -v: whether to print a lot */ -char *total_name[TIME_COUNT]; /* basic function names */ -long total_time[TIME_COUNT]; /* time spent in basic fcts */ -int total_calls[TIME_COUNT]; /* # calls to each fct */ - -bool echo_comments; /* turned off by -eat option */ -bool echo_unknown_commands; /* always true ?? */ -bool force_irredundant; /* -nirr command line option */ -bool skip_make_sparse; -bool kiss; /* -kiss command line option */ -bool pos; /* -pos command line option */ -bool print_solution; /* -x command line option */ -bool recompute_onset; /* -onset command line option */ -bool remove_essential; /* -ness command line option */ -bool single_expand; /* -fast command line option */ -bool summary; /* -s command line option */ -bool trace; /* -t command line option */ -bool unwrap_onset; /* -nunwrap command line option */ -bool use_random_order; /* -random command line option */ -bool use_super_gasp; /* -strong command line option */ -char *filename; /* filename PLA was read from */ - -struct pla_types_struct pla_types[] = { - "-f", F_type, - "-r", R_type, - "-d", D_type, - "-fd", FD_type, - "-fr", FR_type, - "-dr", DR_type, - "-fdr", FDR_type, - "-fc", F_type | CONSTRAINTS_type, - "-rc", R_type | CONSTRAINTS_type, - "-dc", D_type | CONSTRAINTS_type, - "-fdc", FD_type | CONSTRAINTS_type, - "-frc", FR_type | CONSTRAINTS_type, - "-drc", DR_type | CONSTRAINTS_type, - "-fdrc", FDR_type | CONSTRAINTS_type, - "-pleasure", PLEASURE_type, - "-eqn", EQNTOTT_type, - "-eqntott", EQNTOTT_type, - "-kiss", KISS_type, - "-cons", CONSTRAINTS_type, - "-scons", SYMBOLIC_CONSTRAINTS_type, - 0, 0 -}; - - -struct cube_struct cube, temp_cube_save; -struct cdata_struct cdata, temp_cdata_save; - -int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; diff --git a/src/benchmarks/espresso/hack.c b/src/benchmarks/espresso/hack.c deleted file mode 100644 index 6cb76c0..0000000 --- a/src/benchmarks/espresso/hack.c +++ /dev/null @@ -1,632 +0,0 @@ -#include "espresso.h" - -map_dcset(PLA) -pPLA PLA; -{ - int var, i; - pcover Tplus, Tminus, Tplusbar, Tminusbar; - pcover newf, term1, term2, dcset, dcsetbar; - pcube cplus, cminus, last, p; - - if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) - return NULL; - - /* try to find a binary variable named "DONT_CARE" */ - var = -1; - for(i = 0; i < cube.num_binary_vars * 2; i++) { - if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 || - strncmp(PLA->label[i], "DONTCARE", 8) == 0 || - strncmp(PLA->label[i], "dont_care", 9) == 0 || - strncmp(PLA->label[i], "dontcare", 8) == 0) { - var = i/2; - break; - } - } - if (var == -1) { - return NULL; - } - - /* form the cofactor cubes for the don't-care variable */ - cplus = set_save(cube.fullset); - cminus = set_save(cube.fullset); - set_remove(cplus, var*2); - set_remove(cminus, var*2 + 1); - - /* form the don't-care set */ - EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar), - "simpcomp+", Tplus); - EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar), - "simpcomp-", Tminus); - EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1); - EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2); - EXEC(dcset = sf_union(term1, term2), "union ", dcset); - EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D); - EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F); - free_cover(PLA->F); - PLA->F = newf; - free_cover(Tplus); - free_cover(Tminus); - free_cover(Tplusbar); - free_cover(Tminusbar); - free_cover(dcsetbar); - - /* remove any cubes dependent on the DONT_CARE variable */ - (void) sf_active(PLA->F); - foreach_set(PLA->F, last, p) { - if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) { - RESET(p, ACTIVE); - } - } - PLA->F = sf_inactive(PLA->F); - - /* resize the cube and delete the don't-care variable */ - setdown_cube(); - for(i = 2*var+2; i < cube.size; i++) { - PLA->label[i-2] = PLA->label[i]; - } - for(i = var+1; i < cube.num_vars; i++) { - cube.part_size[i-1] = cube.part_size[i]; - } - cube.num_binary_vars--; - cube.num_vars--; - cube_setup(); - PLA->F = sf_delc(PLA->F, 2*var, 2*var+1); - PLA->D = sf_delc(PLA->D, 2*var, 2*var+1); -} - -map_output_symbolic(PLA) -pPLA PLA; -{ - pset_family newF, newD; - pset compress; - symbolic_t *p1; - symbolic_list_t *p2; - int i, bit, tot_size, base, old_size; - - /* Remove the DC-set from the ON-set (is this necessary ??) */ - if (PLA->D->count > 0) { - sf_free(PLA->F); - PLA->F = complement(cube2list(PLA->D, PLA->R)); - } - - /* tot_size = width added for all symbolic variables */ - tot_size = 0; - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) { - fatal("symbolic-output index out of range"); -/* } else if (p2->variable != cube.output) { - fatal("symbolic-output label must be an output");*/ - } - } - tot_size += 1 << p1->symbolic_list_length; - } - - /* adjust the indices to skip over new outputs */ - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - p2->pos += tot_size; - } - } - - /* resize the cube structure -- add enough for the one-hot outputs */ - old_size = cube.size; - cube.part_size[cube.output] += tot_size; - setdown_cube(); - cube_setup(); - - /* insert space in the output part for the one-hot output */ - base = cube.first_part[cube.output]; - PLA->F = sf_addcol(PLA->F, base, tot_size); - PLA->D = sf_addcol(PLA->D, base, tot_size); - PLA->R = sf_addcol(PLA->R, base, tot_size); - - /* do the real work */ - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - newF = new_cover(100); - newD = new_cover(100); - find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0, - &newF, &newD); -/* - * Not sure what this means - find_dc_inputs(PLA, p1->symbolic_list, - base, 1 << p1->symbolic_list_length, &newF, &newD); - */ - free_cover(PLA->F); - PLA->F = newF; -/* - * retain OLD DC-set -- but we've lost the don't-care arc information - * (it defaults to branch to the zero state) - free_cover(PLA->D); - PLA->D = newD; - */ - free_cover(newD); - base += 1 << p1->symbolic_list_length; - } - - /* delete the old outputs, and resize the cube */ - compress = set_full(newF->sf_size); - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - bit = cube.first_part[cube.output] + p2->pos; - set_remove(compress, bit); - } - } - cube.part_size[cube.output] -= newF->sf_size - set_ord(compress); - setdown_cube(); - cube_setup(); - PLA->F = sf_compress(PLA->F, compress); - PLA->D = sf_compress(PLA->D, compress); - if (cube.size != PLA->F->sf_size) fatal("error"); - - /* Quick minimization */ - PLA->F = sf_contain(PLA->F); - PLA->D = sf_contain(PLA->D); - for(i = 0; i < cube.num_vars; i++) { - PLA->F = d1merge(PLA->F, i); - PLA->D = d1merge(PLA->D, i); - } - PLA->F = sf_contain(PLA->F); - PLA->D = sf_contain(PLA->D); - - free_cover(PLA->R); - PLA->R = new_cover(0); - - symbolic_hack_labels(PLA, PLA->symbolic_output, - compress, cube.size, old_size, tot_size); - set_free(compress); -} - - -find_inputs(A, PLA, list, base, value, newF, newD) -pcover A; -pPLA PLA; -symbolic_list_t *list; -int base, value; -pcover *newF, *newD; -{ - pcover S, S1; - register pset last, p; - - /* - * A represents th 'input' values for which the outputs assume - * the integer value 'value - */ - if (list == NIL(symbolic_list_t)) { - /* - * Simulate these inputs against the on-set; then, insert into the - * new on-set a 1 in the proper position - */ - S = cv_intersect(A, PLA->F); - foreach_set(S, last, p) { - set_insert(p, base + value); - } - *newF = sf_append(*newF, S); - - /* - * 'simulate' these inputs against the don't-care set - S = cv_intersect(A, PLA->D); - *newD = sf_append(*newD, S); - */ - - } else { - /* intersect and recur with the OFF-set */ - S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos); - if (A != NIL(set_family_t)) { - S1 = cv_intersect(A, S); - free_cover(S); - S = S1; - } - find_inputs(S, PLA, list->next, base, value*2, newF, newD); - free_cover(S); - - /* intersect and recur with the ON-set */ - S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos); - if (A != NIL(set_family_t)) { - S1 = cv_intersect(A, S); - free_cover(S); - S = S1; - } - find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD); - free_cover(S); - } -} - - -#if 0 -find_dc_inputs(PLA, list, base, maxval, newF, newD) -pPLA PLA; -symbolic_list_t *list; -int base, maxval; -pcover *newF, *newD; -{ - pcover A, S, S1; - symbolic_list_t *p2; - register pset p, last; - register int i; - - /* painfully find the points for which the symbolic output is dc */ - A = NIL(set_family_t); - for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) { - S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos); - if (A == NIL(set_family_t)) { - A = S; - } else { - S1 = cv_intersect(A, S); - free_cover(S); - free_cover(A); - A = S1; - } - } - - S = cv_intersect(A, PLA->F); - *newF = sf_append(*newF, S); - - S = cv_intersect(A, PLA->D); - foreach_set(S, last, p) { - for(i = base; i < base + maxval; i++) { - set_insert(p, i); - } - } - *newD = sf_append(*newD, S); - free_cover(A); -} -#endif - -map_symbolic(PLA) -pPLA PLA; -{ - symbolic_t *p1; - symbolic_list_t *p2; - int var, base, num_vars, num_binary_vars, *new_part_size; - int new_size, size_added, num_deleted_vars, num_added_vars, newvar; - pset compress; - - /* Verify legal values are in the symbolic lists */ - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) { - fatal(".symbolic requires binary variables"); - } - } - } - - /* - * size_added = width added for all symbolic variables - * num_deleted_vars = # binary variables to be deleted - * num_added_vars = # new mv variables - * compress = a cube which will be used to compress the set families - */ - size_added = 0; - num_added_vars = 0; - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - size_added += 1 << p1->symbolic_list_length; - num_added_vars++; - } - compress = set_full(PLA->F->sf_size + size_added); - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - set_remove(compress, p2->variable*2); - set_remove(compress, p2->variable*2+1); - } - } - num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2; - - /* compute the new cube constants */ - num_vars = cube.num_vars - num_deleted_vars + num_added_vars; - num_binary_vars = cube.num_binary_vars - num_deleted_vars; - new_size = cube.size - num_deleted_vars*2 + size_added; - new_part_size = ALLOC(int, num_vars); - new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1]; - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { - new_part_size[var-num_deleted_vars] = cube.part_size[var]; - } - - /* re-size the covers, opening room for the new mv variables */ - base = cube.first_part[cube.output]; - PLA->F = sf_addcol(PLA->F, base, size_added); - PLA->D = sf_addcol(PLA->D, base, size_added); - PLA->R = sf_addcol(PLA->R, base, size_added); - - /* compute the values for the new mv variables */ - newvar = (cube.num_vars - 1) - num_deleted_vars; - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base); - PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base); - PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base); - base += 1 << p1->symbolic_list_length; - new_part_size[newvar++] = 1 << p1->symbolic_list_length; - } - - /* delete the binary variables which disappear */ - PLA->F = sf_compress(PLA->F, compress); - PLA->D = sf_compress(PLA->D, compress); - PLA->R = sf_compress(PLA->R, compress); - - symbolic_hack_labels(PLA, PLA->symbolic, compress, - new_size, cube.size, size_added); - setdown_cube(); - FREE(cube.part_size); - cube.num_vars = num_vars; - cube.num_binary_vars = num_binary_vars; - cube.part_size = new_part_size; - cube_setup(); - set_free(compress); -} - - -pcover map_symbolic_cover(T, list, base) -pcover T; -symbolic_list_t *list; -int base; -{ - pset last, p; - foreach_set(T, last, p) { - form_bitvector(p, base, 0, list); - } - return T; -} - - -form_bitvector(p, base, value, list) -pset p; /* old cube, looking at binary variables */ -int base; /* where in mv cube the new variable starts */ -int value; /* current value for this recursion */ -symbolic_list_t *list; /* current place in the symbolic list */ -{ - if (list == NIL(symbolic_list_t)) { - set_insert(p, base + value); - } else { - switch(GETINPUT(p, list->variable)) { - case ZERO: - form_bitvector(p, base, value*2, list->next); - break; - case ONE: - form_bitvector(p, base, value*2+1, list->next); - break; - case TWO: - form_bitvector(p, base, value*2, list->next); - form_bitvector(p, base, value*2+1, list->next); - break; - default: - fatal("bad cube in form_bitvector"); - } - } -} - - -symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added) -pPLA PLA; -symbolic_t *list; -pset compress; -int new_size, old_size, size_added; -{ - int i, base; - char **oldlabel; - symbolic_t *p1; - symbolic_label_t *p3; - - /* hack with the labels */ - if ((oldlabel = PLA->label) == NIL(char *)) - return 0; - PLA->label = ALLOC(char *, new_size); - for(i = 0; i < new_size; i++) { - PLA->label[i] = NIL(char); - } - - /* copy the binary variable labels and unchanged mv variable labels */ - base = 0; - for(i = 0; i < cube.first_part[cube.output]; i++) { - if (is_in_set(compress, i)) { - PLA->label[base++] = oldlabel[i]; - } else { - if (oldlabel[i] != NIL(char)) { - FREE(oldlabel[i]); - } - } - } - - /* add the user-defined labels for the symbolic outputs */ - for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) { - p3 = p1->symbolic_label; - for(i = 0; i < (1 << p1->symbolic_list_length); i++) { - if (p3 == NIL(symbolic_label_t)) { - PLA->label[base+i] = ALLOC(char, 10); - (void) sprintf(PLA->label[base+i], "X%d", i); - } else { - PLA->label[base+i] = p3->label; - p3 = p3->next; - } - } - base += 1 << p1->symbolic_list_length; - } - - /* copy the labels for the binary outputs which remain */ - for(i = cube.first_part[cube.output]; i < old_size; i++) { - if (is_in_set(compress, i + size_added)) { - PLA->label[base++] = oldlabel[i]; - } else { - if (oldlabel[i] != NIL(char)) { - FREE(oldlabel[i]); - } - } - } - FREE(oldlabel); -} - -static pcover fsm_simplify(F) -pcover F; -{ - pcover D, R; - D = new_cover(0); - R = complement(cube1list(F)); - F = espresso(F, D, R); - free_cover(D); - free_cover(R); - return F; -} - - -disassemble_fsm(PLA, verbose_mode) -pPLA PLA; -int verbose_mode; -{ - int nin, nstates, nout; - int before, after, present_state, next_state, i, j; - pcube next_state_mask, present_state_mask, state_mask, p, p1, last; - pcover go_nowhere, F, tF; - - /* We make the DISGUSTING assumption that the first 'n' outputs have - * been created by .symbolic-output, and represent a one-hot encoding - * of the next state. 'n' is the size of the second-to-last multiple- - * valued variable (i.e., before the outputs - */ - - if (cube.num_vars - cube.num_binary_vars != 2) { - fprintf(stderr, - "use .symbolic and .symbolic-output to specify\n"); - fprintf(stderr, - "the present state and next state field information\n"); - fatal("disassemble_pla: need two multiple-valued variables\n"); - } - - nin = cube.num_binary_vars; - nstates = cube.part_size[cube.num_binary_vars]; - nout = cube.part_size[cube.num_vars - 1]; - if (nout < nstates) { - fprintf(stderr, - "use .symbolic and .symbolic-output to specify\n"); - fprintf(stderr, - "the present state and next state field information\n"); - fatal("disassemble_pla: # outputs < # states\n"); - } - - - present_state = cube.first_part[cube.num_binary_vars]; - present_state_mask = new_cube(); - for(i = 0; i < nstates; i++) { - set_insert(present_state_mask, i + present_state); - } - - next_state = cube.first_part[cube.num_binary_vars+1]; - next_state_mask = new_cube(); - for(i = 0; i < nstates; i++) { - set_insert(next_state_mask, i + next_state); - } - - state_mask = set_or(new_cube(), next_state_mask, present_state_mask); - - F = new_cover(10); - - - /* - * check for arcs which go from ANY state to state #i - */ - for(i = 0; i < nstates; i++) { - tF = new_cover(10); - foreach_set(PLA->F, last, p) { - if (setp_implies(present_state_mask, p)) { /* from any state ! */ - if (is_in_set(p, next_state + i)) { - tF = sf_addset(tF, p); - } - } - } - before = tF->count; - if (before > 0) { - tF = fsm_simplify(tF); - /* don't allow the next state to disappear ... */ - foreach_set(tF, last, p) { - set_insert(p, next_state + i); - } - after = tF->count; - F = sf_append(F, tF); - if (verbose_mode) { - printf("# state EVERY to %d, before=%d after=%d\n", - i, before, after); - } - } - } - - - /* - * some 'arcs' may NOT have a next state -- handle these - * we must unravel the present state part - */ - go_nowhere = new_cover(10); - foreach_set(PLA->F, last, p) { - if (setp_disjoint(p, next_state_mask)) { /* no next state !! */ - go_nowhere = sf_addset(go_nowhere, p); - } - } - before = go_nowhere->count; - go_nowhere = unravel_range(go_nowhere, - cube.num_binary_vars, cube.num_binary_vars); - after = go_nowhere->count; - F = sf_append(F, go_nowhere); - if (verbose_mode) { - printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after); - } - - - /* - * minimize cover for all arcs from state #i to state #j - */ - for(i = 0; i < nstates; i++) { - for(j = 0; j < nstates; j++) { - tF = new_cover(10); - foreach_set(PLA->F, last, p) { - /* not EVERY state */ - if (! setp_implies(present_state_mask, p)) { - if (is_in_set(p, present_state + i)) { - if (is_in_set(p, next_state + j)) { - p1 = set_save(p); - set_diff(p1, p1, state_mask); - set_insert(p1, present_state + i); - set_insert(p1, next_state + j); - tF = sf_addset(tF, p1); - set_free(p1); - } - } - } - } - before = tF->count; - if (before > 0) { - tF = fsm_simplify(tF); - /* don't allow the next state to disappear ... */ - foreach_set(tF, last, p) { - set_insert(p, next_state + j); - } - after = tF->count; - F = sf_append(F, tF); - if (verbose_mode) { - printf("# state %d to %d, before=%d after=%d\n", - i, j, before, after); - } - } - } - } - - - free_cube(state_mask); - free_cube(present_state_mask); - free_cube(next_state_mask); - - free_cover(PLA->F); - PLA->F = F; - free_cover(PLA->D); - PLA->D = new_cover(0); - - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = nin; - cube.num_vars = nin + 3; - cube.part_size = ALLOC(int, cube.num_vars); - cube.part_size[cube.num_binary_vars] = nstates; - cube.part_size[cube.num_binary_vars+1] = nstates; - cube.part_size[cube.num_binary_vars+2] = nout - nstates; - cube_setup(); - - foreach_set(PLA->F, last, p) { - kiss_print_cube(stdout, PLA, p, "~1"); - } -} diff --git a/src/benchmarks/espresso/indep.c b/src/benchmarks/espresso/indep.c deleted file mode 100644 index c462988..0000000 --- a/src/benchmarks/espresso/indep.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - -static sm_matrix *build_intersection_matrix(); - - -#if 0 -/* - * verify that all rows in 'indep' are actually independent ! - */ -static int -verify_indep_set(A, indep) -sm_matrix *A; -sm_row *indep; -{ - register sm_row *prow, *prow1; - register sm_element *p, *p1; - - for(p = indep->first_col; p != 0; p = p->next_col) { - prow = sm_get_row(A, p->col_num); - for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) { - prow1 = sm_get_row(A, p1->col_num); - if (sm_row_intersects(prow, prow1)) { - return 0; - } - } - } - return 1; -} -#endif - -solution_t * -sm_maximal_independent_set(A, weight) -sm_matrix *A; -int *weight; -{ - register sm_row *best_row, *prow; - register sm_element *p; - int least_weight; - sm_row *save; - sm_matrix *B; - solution_t *indep; - - indep = solution_alloc(); - B = build_intersection_matrix(A); - - while (B->nrows > 0) { - /* Find the row which is disjoint from a maximum number of rows */ - best_row = B->first_row; - for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) { - if (prow->length < best_row->length) { - best_row = prow; - } - } - - /* Find which element in this row has least weight */ - if (weight == NIL(int)) { - least_weight = 1; - } else { - prow = sm_get_row(A, best_row->row_num); - least_weight = weight[prow->first_col->col_num]; - for(p = prow->first_col->next_col; p != 0; p = p->next_col) { - if (weight[p->col_num] < least_weight) { - least_weight = weight[p->col_num]; - } - } - } - indep->cost += least_weight; - (void) sm_row_insert(indep->row, best_row->row_num); - - /* Discard the rows which intersect this row */ - save = sm_row_dup(best_row); - for(p = save->first_col; p != 0; p = p->next_col) { - sm_delrow(B, p->col_num); - sm_delcol(B, p->col_num); - } - sm_row_free(save); - } - - sm_free(B); - -/* - if (! verify_indep_set(A, indep->row)) { - fail("sm_maximal_independent_set: row set is not independent"); - } -*/ - return indep; -} - -static sm_matrix * -build_intersection_matrix(A) -sm_matrix *A; -{ - register sm_row *prow, *prow1; - register sm_element *p, *p1; - register sm_col *pcol; - sm_matrix *B; - - /* Build row-intersection matrix */ - B = sm_alloc(); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - - /* Clear flags on all rows we can reach from row 'prow' */ - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { - prow1 = sm_get_row(A, p1->row_num); - prow1->flag = 0; - } - } - - /* Now record which rows can be reached */ - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { - prow1 = sm_get_row(A, p1->row_num); - if (! prow1->flag) { - prow1->flag = 1; - (void) sm_insert(B, prow->row_num, prow1->row_num); - } - } - } - } - - return B; -} diff --git a/src/benchmarks/espresso/irred.c b/src/benchmarks/espresso/irred.c deleted file mode 100644 index 0c49ff3..0000000 --- a/src/benchmarks/espresso/irred.c +++ /dev/null @@ -1,431 +0,0 @@ -#include "espresso.h" - -static void fcube_is_covered(); -static void ftautology(); -static bool ftaut_special_cases(); - - -static int Rp_current; - -/* - * irredundant -- Return a minimal subset of F - */ - -pcover -irredundant(F, D) -pcover F, D; -{ - mark_irredundant(F, D); - return sf_inactive(F); -} - - -/* - * mark_irredundant -- find redundant cubes, and mark them "INACTIVE" - */ - -void -mark_irredundant(F, D) -pcover F, D; -{ - pcover E, Rt, Rp; - pset p, p1, last; - sm_matrix *table; - sm_row *cover; - sm_element *pe; - - /* extract a minimum cover */ - irred_split_cover(F, D, &E, &Rt, &Rp); - table = irred_derive_table(D, E, Rp); - cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0); - - /* mark the cubes for the result */ - foreach_set(F, last, p) { - RESET(p, ACTIVE); - RESET(p, RELESSEN); - } - foreach_set(E, last, p) { - p1 = GETSET(F, SIZE(p)); - assert(setp_equal(p1, p)); - SET(p1, ACTIVE); - SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */ - } - sm_foreach_row_element(cover, pe) { - p1 = GETSET(F, pe->col_num); - SET(p1, ACTIVE); - } - - if (debug & IRRED) { - printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n", - F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count, - cover->length, E->count + cover->length, 0); - } - - free_cover(E); - free_cover(Rt); - free_cover(Rp); - sm_free(table); - sm_row_free(cover); -} - -/* - * irred_split_cover -- find E, Rt, and Rp from the cover F, D - * - * E -- relatively essential cubes - * Rt -- totally redundant cubes - * Rp -- partially redundant cubes - */ - -void -irred_split_cover(F, D, E, Rt, Rp) -pcover F, D; -pcover *E, *Rt, *Rp; -{ - register pcube p, last; - register int index; - pcover R; - pcube *FD, *ED; - - /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */ - index = 0; - foreach_set(F, last, p) { - PUTSIZE(p, index); - index++; - } - - *E = new_cover(10); - *Rt = new_cover(10); - *Rp = new_cover(10); - R = new_cover(10); - - /* Split F into E and R */ - FD = cube2list(F, D); - foreach_set(F, last, p) { - if (cube_is_covered(FD, p)) { - R = sf_addset(R, p); - } else { - *E = sf_addset(*E, p); - } - if (debug & IRRED1) { - (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n", - R->count, (*E)->count, F->count - (R->count + (*E)->count), - print_time(ptime())); - } - } - free_cubelist(FD); - - /* Split R into Rt and Rp */ - ED = cube2list(*E, D); - foreach_set(R, last, p) { - if (cube_is_covered(ED, p)) { - *Rt = sf_addset(*Rt, p); - } else { - *Rp = sf_addset(*Rp, p); - } - if (debug & IRRED1) { - (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n", - (*Rp)->count, (*Rt)->count, - R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime())); - } - } - free_cubelist(ED); - - free_cover(R); -} - -/* - * irred_derive_table -- given the covers D, E and the set of - * partially redundant primes Rp, build a covering table showing - * possible selections of primes to cover Rp. - */ - -sm_matrix * -irred_derive_table(D, E, Rp) -pcover D, E, Rp; -{ - register pcube last, p, *list; - sm_matrix *table; - int size_last_dominance, i; - - /* Mark each cube in DE as not part of the redundant set */ - foreach_set(D, last, p) { - RESET(p, REDUND); - } - foreach_set(E, last, p) { - RESET(p, REDUND); - } - - /* Mark each cube in Rp as partially redundant */ - foreach_set(Rp, last, p) { - SET(p, REDUND); /* belongs to redundant set */ - } - - /* For each cube in Rp, find ways to cover its minterms */ - list = cube3list(D, E, Rp); - table = sm_alloc(); - size_last_dominance = 0; - i = 0; - foreach_set(Rp, last, p) { - Rp_current = SIZE(p); - fcube_is_covered(list, p, table); - RESET(p, REDUND); /* can now consider this cube redundant */ - if (debug & IRRED1) { - (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n", - i, Rp->count, Rp->count - i, - table->nrows, table->ncols, print_time(ptime())); - } - /* try to keep memory limits down by reducing table as we go along */ - if (table->nrows - size_last_dominance > 1000) { - (void) sm_row_dominance(table); - size_last_dominance = table->nrows; - if (debug & IRRED1) { - (void) printf("IRRED1: delete redundant rows, now %dx%d\n", - table->nrows, table->ncols); - } - } - i++; - } - free_cubelist(list); - - return table; -} - -/* cube_is_covered -- determine if a cubelist "covers" a single cube */ -bool -cube_is_covered(T, c) -pcube *T, c; -{ - return tautology(cofactor(T,c)); -} - - - -/* tautology -- answer the tautology question for T */ -bool -tautology(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best, result; - static int taut_level = 0; - - if (debug & TAUT) { - debug_print(T, "TAUTOLOGY", taut_level++); - } - - if ((result = taut_special_cases(T)) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, TAUT); - result = tautology(scofactor(T, cl, best)) && - tautology(scofactor(T, cr, best)); - free_cubelist(T); - free_cube(cl); - free_cube(cr); - } - - if (debug & TAUT) { - printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result)); - } - return result; -} - -/* - * taut_special_cases -- check special cases for tautology - */ - -bool -taut_special_cases(T) -pcube *T; /* will be disposed if answer is determined */ -{ - register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1]; - pcube *A, *B; - int var; - - /* Check for a row of all 1's which implies tautology */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, T[0])) { - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which implies no tautology */ -start: - INLINEset_copy(ceil, T[0]); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - free_cubelist(T); - return FALSE; - } - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If function is unate (and no row of all 1's), then no tautology */ - if (cdata.vars_unate == cdata.vars_active) { - free_cubelist(T); - return FALSE; - - /* If active in a single variable (and no column of 0's) then tautology */ - } else if (cdata.vars_active == 1) { - free_cubelist(T); - return TRUE; - - /* Check for unate variables, and reduce cover if there are any */ - } else if (cdata.vars_unate != 0) { - /* Form a cube "ceil" with full variables in the unate variables */ - (void) set_copy(ceil, cube.emptyset); - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - INLINEset_or(ceil, ceil, cube.var_mask[var]); - } - } - - /* Save only those cubes that are "full" in all unate variables */ - for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { - if (setp_implies(ceil, set_or(temp, p, T[0]))) { - *Tsave++ = p; - } - } - *Tsave++ = NULL; - T[1] = (pcube) Tsave; - - if (debug & TAUT) { - printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", - cdata.vars_unate, CUBELISTSIZE(T)); - } - goto start; - - /* Check for component reduction */ - } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) { - if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) { - return MAYBE; - } else { - free_cubelist(T); - if (tautology(A)) { - free_cubelist(B); - return TRUE; - } else { - return tautology(B); - } - } - } - - /* We tried as hard as we could, but must recurse from here on */ - return MAYBE; -} - -/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */ -static void -fcube_is_covered(T, c, table) -pcube *T, c; -sm_matrix *table; -{ - ftautology(cofactor(T,c), table); -} - - -/* ftautology -- find ways to make a tautology */ -static void -ftautology(T, table) -pcube *T; /* T will be disposed of */ -sm_matrix *table; -{ - register pcube cl, cr; - register int best; - static int ftaut_level = 0; - - if (debug & TAUT) { - debug_print(T, "FIND_TAUTOLOGY", ftaut_level++); - } - - if (ftaut_special_cases(T, table) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, TAUT); - - ftautology(scofactor(T, cl, best), table); - ftautology(scofactor(T, cr, best), table); - - free_cubelist(T); - free_cube(cl); - free_cube(cr); - } - - if (debug & TAUT) { - (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n", - --ftaut_level, table->nrows, table->ncols); - } -} - -static bool -ftaut_special_cases(T, table) -pcube *T; /* will be disposed if answer is determined */ -sm_matrix *table; -{ - register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1]; - int var, rownum; - - /* Check for a row of all 1's in the essential cubes */ - for(T1 = T+2; (p = *T1++) != 0; ) { - if (! TESTP(p, REDUND)) { - if (full_row(p, T[0])) { - /* subspace is covered by essentials -- no new rows for table */ - free_cubelist(T); - return TRUE; - } - } - } - - /* Collect column counts, determine unate variables, etc. */ -start: - massive_count(T); - - /* If function is unate, find the rows of all 1's */ - if (cdata.vars_unate == cdata.vars_active) { - /* find which nonessentials cover this subspace */ - rownum = table->last_row ? table->last_row->row_num+1 : 0; - (void) sm_insert(table, rownum, Rp_current); - for(T1 = T+2; (p = *T1++) != 0; ) { - if (TESTP(p, REDUND)) { - /* See if a redundant cube covers this leaf */ - if (full_row(p, T[0])) { - (void) sm_insert(table, rownum, (int) SIZE(p)); - } - } - } - free_cubelist(T); - return TRUE; - - /* Perform unate reduction if there are any unate variables */ - } else if (cdata.vars_unate != 0) { - /* Form a cube "ceil" with full variables in the unate variables */ - (void) set_copy(ceil, cube.emptyset); - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - INLINEset_or(ceil, ceil, cube.var_mask[var]); - } - } - - /* Save only those cubes that are "full" in all unate variables */ - for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { - if (setp_implies(ceil, set_or(temp, p, T[0]))) { - *Tsave++ = p; - } - } - *Tsave++ = 0; - T[1] = (pcube) Tsave; - - if (debug & TAUT) { - printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", - cdata.vars_unate, CUBELISTSIZE(T)); - } - goto start; - } - - /* Not much we can do about it */ - return MAYBE; -} diff --git a/src/benchmarks/espresso/largest.espresso b/src/benchmarks/espresso/largest.espresso deleted file mode 100644 index 53b0157..0000000 --- a/src/benchmarks/espresso/largest.espresso +++ /dev/null @@ -1,2812 +0,0 @@ -.i 16 -.o 40 -0000000000000000 0000000000000000000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000001001100000 0000000001000000011010000000000000000000 -0000001001100101 0000010010000000011010000000000000000000 -0000001001101010 0001010000000000011010000000000000000000 -0000001001101111 0000100000000000011010000000000000000000 -0000001010100000 0000000001000000101010000000000000000000 -0000001010100101 0000010010000000101010000000000000000000 -0000001010101010 0001010000000000101010000000000000000000 -0000001010101111 0000100000000000101010000000000000000000 -0000001000100000 0000000001000000001010000000000000000000 -0000001000100101 0000010010000000001010000000000000000000 -0000001000101010 0001010000000000001010000000000000000000 -0000001000101111 0000100000000000001010000000000000000000 -0000001011100000 0000000001000000111010000000000000000000 -0000001011100101 0000010010000000111010000000000000000000 -0000001011101010 0001010000000000111010000000000000000000 -0000001011101111 0000100000000000111010000000000000000000 -0000001001010000 0000000001000000010110000000000000000000 -0000001001010101 0000010010000000010110000000000000000000 -0000001001011010 0001010000000000010110000000000000000000 -0000001001011111 0000100000000000010110000000000000000000 -0000001010010000 0000000001000000100110000000000000000000 -0000001010010101 0000010010000000100110000000000000000000 -0000001010011010 0001010000000000100110000000000000000000 -0000001010011111 0000100000000000100110000000000000000000 -0000001000010000 0000000001000000000110000000000000000000 -0000001000010101 0000010010000000000110000000000000000000 -0000001000011010 0001010000000000000110000000000000000000 -0000001000011111 0000100000000000000110000000000000000000 -0000001011010000 0000000001000000110110000000000000000000 -0000001011010101 0000010010000000110110000000000000000000 -0000001011011010 0001010000000000110110000000000000000000 -0000001011011111 0000100000000000110110000000000000000000 -0000001001000000 0000000001000000010010000000000000000000 -0000001001000101 0000010010000000010010000000000000000000 -0000001001001010 0001010000000000010010000000000000000000 -0000001001001111 0000100000000000010010000000000000000000 -0000001010000000 0000000001000000100010000000000000000000 -0000001010000101 0000010010000000100010000000000000000000 -0000001010001010 0001010000000000100010000000000000000000 -0000001010001111 0000100000000000100010000000000000000000 -0000001000000000 0000000001000000000010000000000000000000 -0000001000000101 0000010010000000000010000000000000000000 -0000001000001010 0001010000000000000010000000000000000000 -0000001000001111 0000100000000000000010000000000000000000 -0000001011000000 0000000001000000110010000000000000000000 -0000001011000101 0000010010000000110010000000000000000000 -0000001011001010 0001010000000000110010000000000000000000 -0000001011001111 0000100000000000110010000000000000000000 -0000001001110000 0000000001000000011110000000000000000000 -0000001001110101 0000010010000000011110000000000000000000 -0000001001111010 0001010000000000011110000000000000000000 -0000001001111111 0000100000000000011110000000000000000000 -0000001010110000 0000000001000000101110000000000000000000 -0000001010110101 0000010010000000101110000000000000000000 -0000001010111010 0001010000000000101110000000000000000000 -0000001010111111 0000100000000000101110000000000000000000 -0000001000110000 0000000001000000001110000000000000000000 -0000001000110101 0000010010000000001110000000000000000000 -0000001000111010 0001010000000000001110000000000000000000 -0000001000111111 0000100000000000001110000000000000000000 -0000001011110000 0000000001000000111110000000000000000000 -0000001011110101 0000010010000000111110000000000000000000 -0000001011111010 0001010000000000111110000000000000000000 -0000001011111111 0000100000000000111110000000000000000000 -0000001001100100 0000010011000000011010000000000000000000 -0000001001101000 0001010001000000011010000000000000000000 -0000001001101100 0000100001000000011010000000000000000000 -0000001001100001 0000010011000000011010000000000000000000 -0000001001101001 0001010010000000011010000000000000000000 -0000001001101101 0000110010000000011010000000000000000000 -0000001001100010 0001010001000000011010000000000000000000 -0000001001100110 0001010010000000011010000000000000000000 -0000001001101110 0001110000000000011010000000000000000000 -0000001001100011 0000100001000000011010000000000000000000 -0000001001100111 0000110010000000011010000000000000000000 -0000001001101011 0001110000000000011010000000000000000000 -0000001010100100 0000010011000000101010000000000000000000 -0000001010101000 0001010001000000101010000000000000000000 -0000001010101100 0000100001000000101010000000000000000000 -0000001010100001 0000010011000000101010000000000000000000 -0000001010101001 0001010010000000101010000000000000000000 -0000001010101101 0000110010000000101010000000000000000000 -0000001010100010 0001010001000000101010000000000000000000 -0000001010100110 0001010010000000101010000000000000000000 -0000001010101110 0001110000000000101010000000000000000000 -0000001010100011 0000100001000000101010000000000000000000 -0000001010100111 0000110010000000101010000000000000000000 -0000001010101011 0001110000000000101010000000000000000000 -0000001000100100 0000010011000000001010000000000000000000 -0000001000101000 0001010001000000001010000000000000000000 -0000001000101100 0000100001000000001010000000000000000000 -0000001000100001 0000010011000000001010000000000000000000 -0000001000101001 0001010010000000001010000000000000000000 -0000001000101101 0000110010000000001010000000000000000000 -0000001000100010 0001010001000000001010000000000000000000 -0000001000100110 0001010010000000001010000000000000000000 -0000001000101110 0001110000000000001010000000000000000000 -0000001000100011 0000100001000000001010000000000000000000 -0000001000100111 0000110010000000001010000000000000000000 -0000001000101011 0001110000000000001010000000000000000000 -0000001011100100 0000010011000000111010000000000000000000 -0000001011101000 0001010001000000111010000000000000000000 -0000001011101100 0000100001000000111010000000000000000000 -0000001011100001 0000010011000000111010000000000000000000 -0000001011101001 0001010010000000111010000000000000000000 -0000001011101101 0000110010000000111010000000000000000000 -0000001011100010 0001010001000000111010000000000000000000 -0000001011100110 0001010010000000111010000000000000000000 -0000001011101110 0001110000000000111010000000000000000000 -0000001011100011 0000100001000000111010000000000000000000 -0000001011100111 0000110010000000111010000000000000000000 -0000001011101011 0001110000000000111010000000000000000000 -0000001001010100 0000010011000000010110000000000000000000 -0000001001011000 0001010001000000010110000000000000000000 -0000001001011100 0000100001000000010110000000000000000000 -0000001001010001 0000010011000000010110000000000000000000 -0000001001011001 0001010010000000010110000000000000000000 -0000001001011101 0000110010000000010110000000000000000000 -0000001001010010 0001010001000000010110000000000000000000 -0000001001010110 0001010010000000010110000000000000000000 -0000001001011110 0001110000000000010110000000000000000000 -0000001001010011 0000100001000000010110000000000000000000 -0000001001010111 0000110010000000010110000000000000000000 -0000001001011011 0001110000000000010110000000000000000000 -0000001010010100 0000010011000000100110000000000000000000 -0000001010011000 0001010001000000100110000000000000000000 -0000001010011100 0000100001000000100110000000000000000000 -0000001010010001 0000010011000000100110000000000000000000 -0000001010011001 0001010010000000100110000000000000000000 -0000001010011101 0000110010000000100110000000000000000000 -0000001010010010 0001010001000000100110000000000000000000 -0000001010010110 0001010010000000100110000000000000000000 -0000001010011110 0001110000000000100110000000000000000000 -0000001010010011 0000100001000000100110000000000000000000 -0000001010010111 0000110010000000100110000000000000000000 -0000001010011011 0001110000000000100110000000000000000000 -0000001000010100 0000010011000000000110000000000000000000 -0000001000011000 0001010001000000000110000000000000000000 -0000001000011100 0000100001000000000110000000000000000000 -0000001000010001 0000010011000000000110000000000000000000 -0000001000011001 0001010010000000000110000000000000000000 -0000001000011101 0000110010000000000110000000000000000000 -0000001000010010 0001010001000000000110000000000000000000 -0000001000010110 0001010010000000000110000000000000000000 -0000001000011110 0001110000000000000110000000000000000000 -0000001000010011 0000100001000000000110000000000000000000 -0000001000010111 0000110010000000000110000000000000000000 -0000001000011011 0001110000000000000110000000000000000000 -0000001011010100 0000010011000000110110000000000000000000 -0000001011011000 0001010001000000110110000000000000000000 -0000001011011100 0000100001000000110110000000000000000000 -0000001011010001 0000010011000000110110000000000000000000 -0000001011011001 0001010010000000110110000000000000000000 -0000001011011101 0000110010000000110110000000000000000000 -0000001011010010 0001010001000000110110000000000000000000 -0000001011010110 0001010010000000110110000000000000000000 -0000001011011110 0001110000000000110110000000000000000000 -0000001011010011 0000100001000000110110000000000000000000 -0000001011010111 0000110010000000110110000000000000000000 -0000001011011011 0001110000000000110110000000000000000000 -0000001001000100 0000010011000000010010000000000000000000 -0000001001001000 0001010001000000010010000000000000000000 -0000001001001100 0000100001000000010010000000000000000000 -0000001001000001 0000010011000000010010000000000000000000 -0000001001001001 0001010010000000010010000000000000000000 -0000001001001101 0000110010000000010010000000000000000000 -0000001001000010 0001010001000000010010000000000000000000 -0000001001000110 0001010010000000010010000000000000000000 -0000001001001110 0001110000000000010010000000000000000000 -0000001001000011 0000100001000000010010000000000000000000 -0000001001000111 0000110010000000010010000000000000000000 -0000001001001011 0001110000000000010010000000000000000000 -0000001010000100 0000010011000000100010000000000000000000 -0000001010001000 0001010001000000100010000000000000000000 -0000001010001100 0000100001000000100010000000000000000000 -0000001010000001 0000010011000000100010000000000000000000 -0000001010001001 0001010010000000100010000000000000000000 -0000001010001101 0000110010000000100010000000000000000000 -0000001010000010 0001010001000000100010000000000000000000 -0000001010000110 0001010010000000100010000000000000000000 -0000001010001110 0001110000000000100010000000000000000000 -0000001010000011 0000100001000000100010000000000000000000 -0000001010000111 0000110010000000100010000000000000000000 -0000001010001011 0001110000000000100010000000000000000000 -0000001000000100 0000010011000000000010000000000000000000 -0000001000001000 0001010001000000000010000000000000000000 -0000001000001100 0000100001000000000010000000000000000000 -0000001000000001 0000010011000000000010000000000000000000 -0000001000001001 0001010010000000000010000000000000000000 -0000001000001101 0000110010000000000010000000000000000000 -0000001000000010 0001010001000000000010000000000000000000 -0000001000000110 0001010010000000000010000000000000000000 -0000001000001110 0001110000000000000010000000000000000000 -0000001000000011 0000100001000000000010000000000000000000 -0000001000000111 0000110010000000000010000000000000000000 -0000001000001011 0001110000000000000010000000000000000000 -0000001011000100 0000010011000000110010000000000000000000 -0000001011001000 0001010001000000110010000000000000000000 -0000001011001100 0000100001000000110010000000000000000000 -0000001011000001 0000010011000000110010000000000000000000 -0000001011001001 0001010010000000110010000000000000000000 -0000001011001101 0000110010000000110010000000000000000000 -0000001011000010 0001010001000000110010000000000000000000 -0000001011000110 0001010010000000110010000000000000000000 -0000001011001110 0001110000000000110010000000000000000000 -0000001011000011 0000100001000000110010000000000000000000 -0000001011000111 0000110010000000110010000000000000000000 -0000001011001011 0001110000000000110010000000000000000000 -0000001001110100 0000010011000000011110000000000000000000 -0000001001111000 0001010001000000011110000000000000000000 -0000001001111100 0000100001000000011110000000000000000000 -0000001001110001 0000010011000000011110000000000000000000 -0000001001111001 0001010010000000011110000000000000000000 -0000001001111101 0000110010000000011110000000000000000000 -0000001001110010 0001010001000000011110000000000000000000 -0000001001110110 0001010010000000011110000000000000000000 -0000001001111110 0001110000000000011110000000000000000000 -0000001001110011 0000100001000000011110000000000000000000 -0000001001110111 0000110010000000011110000000000000000000 -0000001001111011 0001110000000000011110000000000000000000 -0000001010110100 0000010011000000101110000000000000000000 -0000001010111000 0001010001000000101110000000000000000000 -0000001010111100 0000100001000000101110000000000000000000 -0000001010110001 0000010011000000101110000000000000000000 -0000001010111001 0001010010000000101110000000000000000000 -0000001010111101 0000110010000000101110000000000000000000 -0000001010110010 0001010001000000101110000000000000000000 -0000001010110110 0001010010000000101110000000000000000000 -0000001010111110 0001110000000000101110000000000000000000 -0000001010110011 0000100001000000101110000000000000000000 -0000001010110111 0000110010000000101110000000000000000000 -0000001010111011 0001110000000000101110000000000000000000 -0000001000110100 0000010011000000001110000000000000000000 -0000001000111000 0001010001000000001110000000000000000000 -0000001000111100 0000100001000000001110000000000000000000 -0000001000110001 0000010011000000001110000000000000000000 -0000001000111001 0001010010000000001110000000000000000000 -0000001000111101 0000110010000000001110000000000000000000 -0000001000110010 0001010001000000001110000000000000000000 -0000001000110110 0001010010000000001110000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000001000111110 0001110000000000001110000000000000000000 -0000001000110011 0000100001000000001110000000000000000000 -0000001000110111 0000110010000000001110000000000000000000 -0000001000111011 0001110000000000001110000000000000000000 -0000001011110100 0000010011000000111110000000000000000000 -0000001011111000 0001010001000000111110000000000000000000 -0000001011111100 0000100001000000111110000000000000000000 -0000001011110001 0000010011000000111110000000000000000000 -0000001011111001 0001010010000000111110000000000000000000 -0000001011111101 0000110010000000111110000000000000000000 -0000001011110010 0001010001000000111110000000000000000000 -0000001011110110 0001010010000000111110000000000000000000 -0000001011111110 0001110000000000111110000000000000000000 -0000001011110011 0000100001000000111110000000000000000000 -0000001011110111 0000110010000000111110000000000000000000 -0000001011111011 0001110000000000111110000000000000000000 -0000001101000000 0000000001010000010010000000000000000000 -0000001110000101 0000010010010000100010000000000000000000 -0000001100101010 0001010000010000001010000000000000000000 -0000001100011111 0000100000010000000110000000000000000000 -0000001101000101 0000010010010000010010000000000000000000 -0000001101001010 0001010000010000010010000000000000000000 -0000001101001111 0000100000010000010010000000000000000000 -0000001110000000 0000000001010000100010000000000000000000 -0000001110001010 0001010000010000100010000000000000000000 -0000001110001111 0000100000010000100010000000000000000000 -0000001100100000 0000000001010000001010000000000000000000 -0000001100100101 0000010010010000001010000000000000000000 -0000001100101111 0000100000010000001010000000000000000000 -0000001100010000 0000000001010000000110000000000000000000 -0000001100010101 0000010010010000000110000000000000000000 -0000001100011010 0001010000010000000110000000000000000000 -0000001101000100 0000010011010000010010000000000000000000 -0000001101001000 0001010001010000010010000000000000000000 -0000001101001100 0000100001010000010010000000000000000000 -0000001101000001 0000010011010000010010000000000000000000 -0000001101001001 0001010010010000010010000000000000000000 -0000001101001101 0000110010010000010010000000000000000000 -0000001101000010 0001010001010000010010000000000000000000 -0000001101000110 0001010010010000010010000000000000000000 -0000001101001110 0001110000010000010010000000000000000000 -0000001101000011 0000100001010000010010000000000000000000 -0000001101000111 0000110010010000010010000000000000000000 -0000001101001011 0001110000010000010010000000000000000000 -0000001110000100 0000010011010000100010000000000000000000 -0000001110001000 0001010001010000100010000000000000000000 -0000001110001100 0000100001010000100010000000000000000000 -0000001110000001 0000010011010000100010000000000000000000 -0000001110001001 0001010010010000100010000000000000000000 -0000001110001101 0000110010010000100010000000000000000000 -0000001110000010 0001010001010000100010000000000000000000 -0000001110000110 0001010010010000100010000000000000000000 -0000001110001110 0001110000010000100010000000000000000000 -0000001110000011 0000100001010000100010000000000000000000 -0000001110000111 0000110010010000100010000000000000000000 -0000001110001011 0001110000010000100010000000000000000000 -0000001100100100 0000010011010000001010000000000000000000 -0000001100101000 0001010001010000001010000000000000000000 -0000001100101100 0000100001010000001010000000000000000000 -0000001100100001 0000010011010000001010000000000000000000 -0000001100101001 0001010010010000001010000000000000000000 -0000001100101101 0000110010010000001010000000000000000000 -0000001100100010 0001010001010000001010000000000000000000 -0000001100100110 0001010010010000001010000000000000000000 -0000001100101110 0001110000010000001010000000000000000000 -0000001100100011 0000100001010000001010000000000000000000 -0000001100100111 0000110010010000001010000000000000000000 -0000001100101011 0001110000010000001010000000000000000000 -0000001100010100 0000010011010000000110000000000000000000 -0000001100011000 0001010001010000000110000000000000000000 -0000001100011100 0000100001010000000110000000000000000000 -0000001100010001 0000010011010000000110000000000000000000 -0000001100011001 0001010010010000000110000000000000000000 -0000001100011101 0000110010010000000110000000000000000000 -0000001100010010 0001010001010000000110000000000000000000 -0000001100010110 0001010010010000000110000000000000000000 -0000001100011110 0001110000010000000110000000000000000000 -0000001100010011 0000100001010000000110000000000000000000 -0000001100010111 0000110010010000000110000000000000000000 -0000001100011011 0001110000010000000110000000000000000000 -0000100001100000 0000000001001000011000000000000000000000 -0000100001100101 0000010010001000011000000000000000000000 -0000100001101010 0001010000001000011000000000000000000000 -0000100001101111 0000100000001000011000000000000000000000 -0000100010100000 0000000001001000101000000000000000000000 -0000100010100101 0000010010001000101000000000000000000000 -0000100010101010 0001010000001000101000000000000000000000 -0000100010101111 0000100000001000101000000000000000000000 -0000100000100000 0000000001001000001000000000000000000000 -0000100000100101 0000010010001000001000000000000000000000 -0000100000101010 0001010000001000001000000000000000000000 -0000100000101111 0000100000001000001000000000000000000000 -0000100011100000 0000000001001000111000000000000000000000 -0000100011100101 0000010010001000111000000000000000000000 -0000100011101010 0001010000001000111000000000000000000000 -0000100011101111 0000100000001000111000000000000000000000 -0000100001010000 0000000001001000010100000000000000000000 -0000100001010101 0000010010001000010100000000000000000000 -0000100001011010 0001010000001000010100000000000000000000 -0000100001011111 0000100000001000010100000000000000000000 -0000100010010000 0000000001001000100100000000000000000000 -0000100010010101 0000010010001000100100000000000000000000 -0000100010011010 0001010000001000100100000000000000000000 -0000100010011111 0000100000001000100100000000000000000000 -0000100000010000 0000000001001000000100000000000000000000 -0000100000010101 0000010010001000000100000000000000000000 -0000100000011010 0001010000001000000100000000000000000000 -0000100000011111 0000100000001000000100000000000000000000 -0000100011010000 0000000001001000110100000000000000000000 -0000100011010101 0000010010001000110100000000000000000000 -0000100011011010 0001010000001000110100000000000000000000 -0000100011011111 0000100000001000110100000000000000000000 -0000100001000000 0000000001001000010000000000000000000000 -0000100001000101 0000010010001000010000000000000000000000 -0000100001001010 0001010000001000010000000000000000000000 -0000100001001111 0000100000001000010000000000000000000000 -0000100010000000 0000000001001000100000000000000000000000 -0000100010000101 0000010010001000100000000000000000000000 -0000100010001010 0001010000001000100000000000000000000000 -0000100010001111 0000100000001000100000000000000000000000 -0000100000000000 0000000001001000000000000000000000000000 -0000100000000101 0000010010001000000000000000000000000000 -0000100000001010 0001010000001000000000000000000000000000 -0000100000001111 0000100000001000000000000000000000000000 -0000100011000000 0000000001001000110000000000000000000000 -0000100011000101 0000010010001000110000000000000000000000 -0000100011001010 0001010000001000110000000000000000000000 -0000100011001111 0000100000001000110000000000000000000000 -0000100001110000 0000000001001000011100000000000000000000 -0000100001110101 0000010010001000011100000000000000000000 -0000100001111010 0001010000001000011100000000000000000000 -0000100001111111 0000100000001000011100000000000000000000 -0000100010110000 0000000001001000101100000000000000000000 -0000100010110101 0000010010001000101100000000000000000000 -0000100010111010 0001010000001000101100000000000000000000 -0000100010111111 0000100000001000101100000000000000000000 -0000100000110000 0000000001001000001100000000000000000000 -0000100000110101 0000010010001000001100000000000000000000 -0000100000111010 0001010000001000001100000000000000000000 -0000100000111111 0000100000001000001100000000000000000000 -0000100011110000 0000000001001000111100000000000000000000 -0000100011110101 0000010010001000111100000000000000000000 -0000100011111010 0001010000001000111100000000000000000000 -0000100011111111 0000100000001000111100000000000000000000 -0000100001100100 0000010011001000011000000000000000000000 -0000100001101000 0001010001001000011000000000000000000000 -0000100001101100 0000100001001000011000000000000000000000 -0000100001100001 0000010011001000011000000000000000000000 -0000100001101001 0001010010001000011000000000000000000000 -0000100001101101 0000110010001000011000000000000000000000 -0000100001100010 0001010001001000011000000000000000000000 -0000100001100110 0001010010001000011000000000000000000000 -0000100001101110 0001110000001000011000000000000000000000 -0000100001100011 0000100001001000011000000000000000000000 -0000100001100111 0000110010001000011000000000000000000000 -0000100001101011 0001110000001000011000000000000000000000 -0000100010100100 0000010011001000101000000000000000000000 -0000100010101000 0001010001001000101000000000000000000000 -0000100010101100 0000100001001000101000000000000000000000 -0000100010100001 0000010011001000101000000000000000000000 -0000100010101001 0001010010001000101000000000000000000000 -0000100010101101 0000110010001000101000000000000000000000 -0000100010100010 0001010001001000101000000000000000000000 -0000100010100110 0001010010001000101000000000000000000000 -0000100010101110 0001110000001000101000000000000000000000 -0000100010100011 0000100001001000101000000000000000000000 -0000100010100111 0000110010001000101000000000000000000000 -0000100010101011 0001110000001000101000000000000000000000 -0000100000100100 0000010011001000001000000000000000000000 -0000100000101000 0001010001001000001000000000000000000000 -0000100000101100 0000100001001000001000000000000000000000 -0000100000100001 0000010011001000001000000000000000000000 -0000100000101001 0001010010001000001000000000000000000000 -0000100000101101 0000110010001000001000000000000000000000 -0000100000100010 0001010001001000001000000000000000000000 -0000100000100110 0001010010001000001000000000000000000000 -0000100000101110 0001110000001000001000000000000000000000 -0000100000100011 0000100001001000001000000000000000000000 -0000100000100111 0000110010001000001000000000000000000000 -0000100000101011 0001110000001000001000000000000000000000 -0000100011100100 0000010011001000111000000000000000000000 -0000100011101000 0001010001001000111000000000000000000000 -0000100011101100 0000100001001000111000000000000000000000 -0000100011100001 0000010011001000111000000000000000000000 -0000100011101001 0001010010001000111000000000000000000000 -0000100011101101 0000110010001000111000000000000000000000 -0000100011100010 0001010001001000111000000000000000000000 -0000100011100110 0001010010001000111000000000000000000000 -0000100011101110 0001110000001000111000000000000000000000 -0000100011100011 0000100001001000111000000000000000000000 -0000100011100111 0000110010001000111000000000000000000000 -0000100011101011 0001110000001000111000000000000000000000 -0000100001010100 0000010011001000010100000000000000000000 -0000100001011000 0001010001001000010100000000000000000000 -0000100001011100 0000100001001000010100000000000000000000 -0000100001010001 0000010011001000010100000000000000000000 -0000100001011001 0001010010001000010100000000000000000000 -0000100001011101 0000110010001000010100000000000000000000 -0000100001010010 0001010001001000010100000000000000000000 -0000100001010110 0001010010001000010100000000000000000000 -0000100001011110 0001110000001000010100000000000000000000 -0000100001010011 0000100001001000010100000000000000000000 -0000100001010111 0000110010001000010100000000000000000000 -0000100001011011 0001110000001000010100000000000000000000 -0000100010010100 0000010011001000100100000000000000000000 -0000100010011000 0001010001001000100100000000000000000000 -0000100010011100 0000100001001000100100000000000000000000 -0000100010010001 0000010011001000100100000000000000000000 -0000100010011001 0001010010001000100100000000000000000000 -0000100010011101 0000110010001000100100000000000000000000 -0000100010010010 0001010001001000100100000000000000000000 -0000100010010110 0001010010001000100100000000000000000000 -0000100010011110 0001110000001000100100000000000000000000 -0000100010010011 0000100001001000100100000000000000000000 -0000100010010111 0000110010001000100100000000000000000000 -0000100010011011 0001110000001000100100000000000000000000 -0000100000010100 0000010011001000000100000000000000000000 -0000100000011000 0001010001001000000100000000000000000000 -0000100000011100 0000100001001000000100000000000000000000 -0000100000010001 0000010011001000000100000000000000000000 -0000100000011001 0001010010001000000100000000000000000000 -0000100000011101 0000110010001000000100000000000000000000 -0000100000010010 0001010001001000000100000000000000000000 -0000100000010110 0001010010001000000100000000000000000000 -0000100000011110 0001110000001000000100000000000000000000 -0000100000010011 0000100001001000000100000000000000000000 -0000100000010111 0000110010001000000100000000000000000000 -0000100000011011 0001110000001000000100000000000000000000 -0000100011010100 0000010011001000110100000000000000000000 -0000100011011000 0001010001001000110100000000000000000000 -0000100011011100 0000100001001000110100000000000000000000 -0000100011010001 0000010011001000110100000000000000000000 -0000100011011001 0001010010001000110100000000000000000000 -0000100011011101 0000110010001000110100000000000000000000 -0000100011010010 0001010001001000110100000000000000000000 -0000100011010110 0001010010001000110100000000000000000000 -0000100011011110 0001110000001000110100000000000000000000 -0000100011010011 0000100001001000110100000000000000000000 -0000100011010111 0000110010001000110100000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000100011011011 0001110000001000110100000000000000000000 -0000100001000100 0000010011001000010000000000000000000000 -0000100001001000 0001010001001000010000000000000000000000 -0000100001001100 0000100001001000010000000000000000000000 -0000100001000001 0000010011001000010000000000000000000000 -0000100001001001 0001010010001000010000000000000000000000 -0000100001001101 0000110010001000010000000000000000000000 -0000100001000010 0001010001001000010000000000000000000000 -0000100001000110 0001010010001000010000000000000000000000 -0000100001001110 0001110000001000010000000000000000000000 -0000100001000011 0000100001001000010000000000000000000000 -0000100001000111 0000110010001000010000000000000000000000 -0000100001001011 0001110000001000010000000000000000000000 -0000100010000100 0000010011001000100000000000000000000000 -0000100010001000 0001010001001000100000000000000000000000 -0000100010001100 0000100001001000100000000000000000000000 -0000100010000001 0000010011001000100000000000000000000000 -0000100010001001 0001010010001000100000000000000000000000 -0000100010001101 0000110010001000100000000000000000000000 -0000100010000010 0001010001001000100000000000000000000000 -0000100010000110 0001010010001000100000000000000000000000 -0000100010001110 0001110000001000100000000000000000000000 -0000100010000011 0000100001001000100000000000000000000000 -0000100010000111 0000110010001000100000000000000000000000 -0000100010001011 0001110000001000100000000000000000000000 -0000100000000100 0000010011001000000000000000000000000000 -0000100000001000 0001010001001000000000000000000000000000 -0000100000001100 0000100001001000000000000000000000000000 -0000100000000001 0000010011001000000000000000000000000000 -0000100000001001 0001010010001000000000000000000000000000 -0000100000001101 0000110010001000000000000000000000000000 -0000100000000010 0001010001001000000000000000000000000000 -0000100000000110 0001010010001000000000000000000000000000 -0000100000001110 0001110000001000000000000000000000000000 -0000100000000011 0000100001001000000000000000000000000000 -0000100000000111 0000110010001000000000000000000000000000 -0000100000001011 0001110000001000000000000000000000000000 -0000100011000100 0000010011001000110000000000000000000000 -0000100011001000 0001010001001000110000000000000000000000 -0000100011001100 0000100001001000110000000000000000000000 -0000100011000001 0000010011001000110000000000000000000000 -0000100011001001 0001010010001000110000000000000000000000 -0000100011001101 0000110010001000110000000000000000000000 -0000100011000010 0001010001001000110000000000000000000000 -0000100011000110 0001010010001000110000000000000000000000 -0000100011001110 0001110000001000110000000000000000000000 -0000100011000011 0000100001001000110000000000000000000000 -0000100011000111 0000110010001000110000000000000000000000 -0000100011001011 0001110000001000110000000000000000000000 -0000100001110100 0000010011001000011100000000000000000000 -0000100001111000 0001010001001000011100000000000000000000 -0000100001111100 0000100001001000011100000000000000000000 -0000100001110001 0000010011001000011100000000000000000000 -0000100001111001 0001010010001000011100000000000000000000 -0000100001111101 0000110010001000011100000000000000000000 -0000100001110010 0001010001001000011100000000000000000000 -0000100001110110 0001010010001000011100000000000000000000 -0000100001111110 0001110000001000011100000000000000000000 -0000100001110011 0000100001001000011100000000000000000000 -0000100001110111 0000110010001000011100000000000000000000 -0000100001111011 0001110000001000011100000000000000000000 -0000100010110100 0000010011001000101100000000000000000000 -0000100010111000 0001010001001000101100000000000000000000 -0000100010111100 0000100001001000101100000000000000000000 -0000100010110001 0000010011001000101100000000000000000000 -0000100010111001 0001010010001000101100000000000000000000 -0000100010111101 0000110010001000101100000000000000000000 -0000100010110010 0001010001001000101100000000000000000000 -0000100010110110 0001010010001000101100000000000000000000 -0000100010111110 0001110000001000101100000000000000000000 -0000100010110011 0000100001001000101100000000000000000000 -0000100010110111 0000110010001000101100000000000000000000 -0000100010111011 0001110000001000101100000000000000000000 -0000100000110100 0000010011001000001100000000000000000000 -0000100000111000 0001010001001000001100000000000000000000 -0000100000111100 0000100001001000001100000000000000000000 -0000100000110001 0000010011001000001100000000000000000000 -0000100000111001 0001010010001000001100000000000000000000 -0000100000111101 0000110010001000001100000000000000000000 -0000100000110010 0001010001001000001100000000000000000000 -0000100000110110 0001010010001000001100000000000000000000 -0000100000111110 0001110000001000001100000000000000000000 -0000100000110011 0000100001001000001100000000000000000000 -0000100000110111 0000110010001000001100000000000000000000 -0000100000111011 0001110000001000001100000000000000000000 -0000100011110100 0000010011001000111100000000000000000000 -0000100011111000 0001010001001000111100000000000000000000 -0000100011111100 0000100001001000111100000000000000000000 -0000100011110001 0000010011001000111100000000000000000000 -0000100011111001 0001010010001000111100000000000000000000 -0000100011111101 0000110010001000111100000000000000000000 -0000100011110010 0001010001001000111100000000000000000000 -0000100011110110 0001010010001000111100000000000000000000 -0000100011111110 0001110000001000111100000000000000000000 -0000100011110011 0000100001001000111100000000000000000000 -0000100011110111 0000110010001000111100000000000000000000 -0000100011111011 0001110000001000111100000000000000000000 -0000100000000000 0000000001001000000000000000000000000000 -0000100000000101 0000010010001000000000000000000000000000 -0000100000001010 0001010000001000000000000000000000000000 -0000100000001111 0000100000001000000000000000000000000000 -0000100000000100 0000010011001000000000000000000000000000 -0000100000001000 0001010001001000000000000000000000000000 -0000100000001100 0000100001001000000000000000000000000000 -0000100000000001 0000010011001000000000000000000000000000 -0000100000001001 0001010010001000000000000000000000000000 -0000100000001101 0000110010001000000000000000000000000000 -0000100000000010 0001010001001000000000000000000000000000 -0000100000000110 0001010010001000000000000000000000000000 -0000100000001110 0001110000001000000000000000000000000000 -0000100000000011 0000100001001000000000000000000000000000 -0000100000000111 0000110010001000000000000000000000000000 -0000100000001011 0001110000001000000000000000000000000000 -0000010011101010 0001010000000000111011000000000000000000 -0000010011011111 0000100000000000110111000000000000000000 -0000010011100000 0000000001000000111011000000000000000000 -0000010011100101 0000010010000000111011000000000000000000 -0000010011101111 0000100000000000111011000000000000000000 -0000010011010000 0000000001000000110111000000000000000000 -0000010011010101 0000010010000000110111000000000000000000 -0000010011011010 0001010000000000110111000000000000000000 -0000010011100100 0000010011000000111011000000000000000000 -0000010011101000 0001010001000000111011000000000000000000 -0000010011101100 0000100001000000111011000000000000000000 -0000010011100001 0000010011000000111011000000000000000000 -0000010011101001 0001010010000000111011000000000000000000 -0000010011101101 0000110010000000111011000000000000000000 -0000010011100010 0001010001000000111011000000000000000000 -0000010011100110 0001010010000000111011000000000000000000 -0000010011101110 0001110000000000111011000000000000000000 -0000010011100011 0000100001000000111011000000000000000000 -0000010011100111 0000110010000000111011000000000000000000 -0000010011101011 0001110000000000111011000000000000000000 -0000010011010100 0000010011000000110111000000000000000000 -0000010011011000 0001010001000000110111000000000000000000 -0000010011011100 0000100001000000110111000000000000000000 -0000010011010001 0000010011000000110111000000000000000000 -0000010011011001 0001010010000000110111000000000000000000 -0000010011011101 0000110010000000110111000000000000000000 -0000010011010010 0001010001000000110111000000000000000000 -0000010011010110 0001010010000000110111000000000000000000 -0000010011011110 0001110000000000110111000000000000000000 -0000010011010011 0000100001000000110111000000000000000000 -0000010011010111 0000110010000000110111000000000000000000 -0000010011011011 0001110000000000110111000000000000000000 -0000001001110000 0000000001000000011110000000000000000000 -0000001010110101 0000010010000000101110000000000000000000 -0000001011101010 0001010000000000111010000000000000000000 -0000001011011111 0000100000000000110110000000000000000000 -0000001001110101 0000010010000000011110000000000000000000 -0000001001111010 0001010000000000011110000000000000000000 -0000001001111111 0000100000000000011110000000000000000000 -0000001010110000 0000000001000000101110000000000000000000 -0000001010111010 0001010000000000101110000000000000000000 -0000001010111111 0000100000000000101110000000000000000000 -0000001011100000 0000000001000000111010000000000000000000 -0000001011100101 0000010010000000111010000000000000000000 -0000001011101111 0000100000000000111010000000000000000000 -0000001011010000 0000000001000000110110000000000000000000 -0000001011010101 0000010010000000110110000000000000000000 -0000001011011010 0001010000000000110110000000000000000000 -0000001001110100 0000010011000000011110000000000000000000 -0000001001111000 0001010001000000011110000000000000000000 -0000001001111100 0000100001000000011110000000000000000000 -0000001001110001 0000010011000000011110000000000000000000 -0000001001111001 0001010010000000011110000000000000000000 -0000001001111101 0000110010000000011110000000000000000000 -0000001001110010 0001010001000000011110000000000000000000 -0000001001110110 0001010010000000011110000000000000000000 -0000001001111110 0001110000000000011110000000000000000000 -0000001001110011 0000100001000000011110000000000000000000 -0000001001110111 0000110010000000011110000000000000000000 -0000001001111011 0001110000000000011110000000000000000000 -0000001010110100 0000010011000000101110000000000000000000 -0000001010111000 0001010001000000101110000000000000000000 -0000001010111100 0000100001000000101110000000000000000000 -0000001010110001 0000010011000000101110000000000000000000 -0000001010111001 0001010010000000101110000000000000000000 -0000001010111101 0000110010000000101110000000000000000000 -0000001010110010 0001010001000000101110000000000000000000 -0000001010110110 0001010010000000101110000000000000000000 -0000001010111110 0001110000000000101110000000000000000000 -0000001010110011 0000100001000000101110000000000000000000 -0000001010110111 0000110010000000101110000000000000000000 -0000001010111011 0001110000000000101110000000000000000000 -0000001011100100 0000010011000000111010000000000000000000 -0000001011101000 0001010001000000111010000000000000000000 -0000001011101100 0000100001000000111010000000000000000000 -0000001011100001 0000010011000000111010000000000000000000 -0000001011101001 0001010010000000111010000000000000000000 -0000001011101101 0000110010000000111010000000000000000000 -0000001011100010 0001010001000000111010000000000000000000 -0000001011100110 0001010010000000111010000000000000000000 -0000001011101110 0001110000000000111010000000000000000000 -0000001011100011 0000100001000000111010000000000000000000 -0000001011100111 0000110010000000111010000000000000000000 -0000001011101011 0001110000000000111010000000000000000000 -0000001011010100 0000010011000000110110000000000000000000 -0000001011011000 0001010001000000110110000000000000000000 -0000001011011100 0000100001000000110110000000000000000000 -0000001011010001 0000010011000000110110000000000000000000 -0000001011011001 0001010010000000110110000000000000000000 -0000001011011101 0000110010000000110110000000000000000000 -0000001011010010 0001010001000000110110000000000000000000 -0000001011010110 0001010010000000110110000000000000000000 -0000001011011110 0001110000000000110110000000000000000000 -0000001011010011 0000100001000000110110000000000000000000 -0000001011010111 0000110010000000110110000000000000000000 -0000001011011011 0001110000000000110110000000000000000000 -0000100101000101 0000010010000100010000000000000000000000 -0000100101001010 0001010000000100010000000000000000000000 -0000100101001111 0000100000000100010000000000000000000000 -0000100110000000 0000000001000100100000000000000000000000 -0000100110001010 0001010000000100100000000000000000000000 -0000100110001111 0000100000000100100000000000000000000000 -0000100100100000 0000000001000100001000000000000000000000 -0000100100100101 0000010010000100001000000000000000000000 -0000100100101111 0000100000000100001000000000000000000000 -0000100100010000 0000000001000100000100000000000000000000 -0000100100010101 0000010010000100000100000000000000000000 -0000100100011010 0001010000000100000100000000000000000000 -0000100101001001 0001010010000100010000000000000000000000 -0000100101001101 0000110010000100010000000000000000000000 -0000100101000110 0001010010000100010000000000000000000000 -0000100101001110 0001110000000100010000000000000000000000 -0000100101000111 0000110010000100010000000000000000000000 -0000100101001011 0001110000000100010000000000000000000000 -0000100110001000 0001010001000100100000000000000000000000 -0000100110001100 0000100001000100100000000000000000000000 -0000100110000010 0001010001000100100000000000000000000000 -0000100110001110 0001110000000100100000000000000000000000 -0000100110000011 0000100001000100100000000000000000000000 -0000100110001011 0001110000000100100000000000000000000000 -0000100100100100 0000010011000100001000000000000000000000 -0000100100101100 0000100001000100001000000000000000000000 -0000100100100001 0000010011000100001000000000000000000000 -0000100100101101 0000110010000100001000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000100100100011 0000100001000100001000000000000000000000 -0000100100100111 0000110010000100001000000000000000000000 -0000100100010100 0000010011000100000100000000000000000000 -0000100100011000 0001010001000100000100000000000000000000 -0000100100010001 0000010011000100000100000000000000000000 -0000100100011001 0001010010000100000100000000000000000000 -0000100100010010 0001010001000100000100000000000000000000 -0000100100010110 0001010010000100000100000000000000000000 -0000111001101010 0001010000000000011000000010000000000000 -0000111010101010 0001010000000000101000000010000000000000 -0000111000101010 0001010000000000001000000010000000000000 -0000111011101010 0001010000000000111000000010000000000000 -0000111001011111 0000100000000000010100000010000000000000 -0000111010011111 0000100000000000100100000010000000000000 -0000111000011111 0000100000000000000100000010000000000000 -0000111011011111 0000100000000000110100000010000000000000 -0000111001101000 0001010001000000011000000010000000000000 -0000111001101001 0001010010000000011000000010000000000000 -0000111001100010 0001010001000000011000000010000000000000 -0000111001100110 0001010010000000011000000010000000000000 -0000111001101110 0001110000000000011000000010000000000000 -0000111001101011 0001110000000000011000000010000000000000 -0000111010101000 0001010001000000101000000010000000000000 -0000111010101001 0001010010000000101000000010000000000000 -0000111010100010 0001010001000000101000000010000000000000 -0000111010100110 0001010010000000101000000010000000000000 -0000111010101110 0001110000000000101000000010000000000000 -0000111010101011 0001110000000000101000000010000000000000 -0000111001011100 0000100001000000010100000010000000000000 -0000111001011101 0000110010000000010100000010000000000000 -0000111001011110 0001110000000000010100000010000000000000 -0000111001010011 0000100001000000010100000010000000000000 -0000111001010111 0000110010000000010100000010000000000000 -0000111001011011 0001110000000000010100000010000000000000 -0000111010011100 0000100001000000100100000010000000000000 -0000111010011101 0000110010000000100100000010000000000000 -0000111010011110 0001110000000000100100000010000000000000 -0000111010010011 0000100001000000100100000010000000000000 -0000111010010111 0000110010000000100100000010000000000000 -0000111010011011 0001110000000000100100000010000000000000 -0000110101100000 0000000001000000011000010100000000101000 -0000110101100101 0000010010000000011000010100000000101000 -0000110101101010 0001010000000000011000010100000000101000 -0000110101101111 0000100000000000011000010100000000101000 -0000110110100000 0000000001000000101000010100000000101000 -0000110110100101 0000010010000000101000010100000000101000 -0000110110101010 0001010000000000101000010100000000101000 -0000110110101111 0000100000000000101000010100000000101000 -0000110100100000 0000000001000000001000010100000000101000 -0000110100100101 0000010010000000001000010100000000101000 -0000110100101010 0001010000000000001000010100000000101000 -0000110100101111 0000100000000000001000010100000000101000 -0000110111100000 0000000001000000111000010100000000101000 -0000110111100101 0000010010000000111000010100000000101000 -0000110111101010 0001010000000000111000010100000000101000 -0000110111101111 0000100000000000111000010100000000101000 -0000110101010000 0000000001000000010100010100000000101000 -0000110101010101 0000010010000000010100010100000000101000 -0000110101011010 0001010000000000010100010100000000101000 -0000110101011111 0000100000000000010100010100000000101000 -0000110110010000 0000000001000000100100010100000000101000 -0000110110010101 0000010010000000100100010100000000101000 -0000110110011010 0001010000000000100100010100000000101000 -0000110110011111 0000100000000000100100010100000000101000 -0000110100010000 0000000001000000000100010100000000101000 -0000110100010101 0000010010000000000100010100000000101000 -0000110100011010 0001010000000000000100010100000000101000 -0000110100011111 0000100000000000000100010100000000101000 -0000110111010000 0000000001000000110100010100000000101000 -0000110111010101 0000010010000000110100010100000000101000 -0000110111011010 0001010000000000110100010100000000101000 -0000110111011111 0000100000000000110100010100000000101000 -0000110101000000 0000000001000000010000010100000000101000 -0000110101000101 0000010010000000010000010100000000101000 -0000110101001010 0001010000000000010000010100000000101000 -0000110101001111 0000100000000000010000010100000000101000 -0000110110000000 0000000001000000100000010100000000101000 -0000110110000101 0000010010000000100000010100000000101000 -0000110110001010 0001010000000000100000010100000000101000 -0000110110001111 0000100000000000100000010100000000101000 -0000110100000000 0000000001000000000000010100000000101000 -0000110100000101 0000010010000000000000010100000000101000 -0000110100001010 0001010000000000000000010100000000101000 -0000110100001111 0000100000000000000000010100000000101000 -0000110111000000 0000000001000000110000010100000000101000 -0000110111000101 0000010010000000110000010100000000101000 -0000110111001010 0001010000000000110000010100000000101000 -0000110111001111 0000100000000000110000010100000000101000 -0000110101110000 0000000001000000011100010100000000101000 -0000110101110101 0000010010000000011100010100000000101000 -0000110101111010 0001010000000000011100010100000000101000 -0000110101111111 0000100000000000011100010100000000101000 -0000110110110000 0000000001000000101100010100000000101000 -0000110110110101 0000010010000000101100010100000000101000 -0000110110111010 0001010000000000101100010100000000101000 -0000110110111111 0000100000000000101100010100000000101000 -0000110100110000 0000000001000000001100010100000000101000 -0000110100110101 0000010010000000001100010100000000101000 -0000110100111010 0001010000000000001100010100000000101000 -0000110100111111 0000100000000000001100010100000000101000 -0000110111110000 0000000001000000111100010100000000101000 -0000110111110101 0000010010000000111100010100000000101000 -0000110111111010 0001010000000000111100010100000000101000 -0000110111111111 0000100000000000111100010100000000101000 -0000110101100100 0000010011000000011000010100000000101000 -0000110101101000 0001010001000000011000010100000000101000 -0000110101101100 0000100001000000011000010100000000101000 -0000110101100001 0000010011000000011000010100000000101000 -0000110101101001 0001010010000000011000010100000000101000 -0000110101101101 0000110010000000011000010100000000101000 -0000110101100010 0001010001000000011000010100000000101000 -0000110101100110 0001010010000000011000010100000000101000 -0000110101101110 0001110000000000011000010100000000101000 -0000110101100011 0000100001000000011000010100000000101000 -0000110101100111 0000110010000000011000010100000000101000 -0000110101101011 0001110000000000011000010100000000101000 -0000110110100100 0000010011000000101000010100000000101000 -0000110110101000 0001010001000000101000010100000000101000 -0000110110101100 0000100001000000101000010100000000101000 -0000110110100001 0000010011000000101000010100000000101000 -0000110110101001 0001010010000000101000010100000000101000 -0000110110101101 0000110010000000101000010100000000101000 -0000110110100010 0001010001000000101000010100000000101000 -0000110110100110 0001010010000000101000010100000000101000 -0000110110101110 0001110000000000101000010100000000101000 -0000110110100011 0000100001000000101000010100000000101000 -0000110110100111 0000110010000000101000010100000000101000 -0000110110101011 0001110000000000101000010100000000101000 -0000110100100100 0000010011000000001000010100000000101000 -0000110100101000 0001010001000000001000010100000000101000 -0000110100101100 0000100001000000001000010100000000101000 -0000110100100001 0000010011000000001000010100000000101000 -0000110100101001 0001010010000000001000010100000000101000 -0000110100101101 0000110010000000001000010100000000101000 -0000110100100010 0001010001000000001000010100000000101000 -0000110100100110 0001010010000000001000010100000000101000 -0000110100101110 0001110000000000001000010100000000101000 -0000110100100011 0000100001000000001000010100000000101000 -0000110100100111 0000110010000000001000010100000000101000 -0000110100101011 0001110000000000001000010100000000101000 -0000110111100100 0000010011000000111000010100000000101000 -0000110111101000 0001010001000000111000010100000000101000 -0000110111101100 0000100001000000111000010100000000101000 -0000110111100001 0000010011000000111000010100000000101000 -0000110111101001 0001010010000000111000010100000000101000 -0000110111101101 0000110010000000111000010100000000101000 -0000110111100010 0001010001000000111000010100000000101000 -0000110111100110 0001010010000000111000010100000000101000 -0000110111101110 0001110000000000111000010100000000101000 -0000110111100011 0000100001000000111000010100000000101000 -0000110111100111 0000110010000000111000010100000000101000 -0000110111101011 0001110000000000111000010100000000101000 -0000110101010100 0000010011000000010100010100000000101000 -0000110101011000 0001010001000000010100010100000000101000 -0000110101011100 0000100001000000010100010100000000101000 -0000110101010001 0000010011000000010100010100000000101000 -0000110101011001 0001010010000000010100010100000000101000 -0000110101011101 0000110010000000010100010100000000101000 -0000110101010010 0001010001000000010100010100000000101000 -0000110101010110 0001010010000000010100010100000000101000 -0000110101011110 0001110000000000010100010100000000101000 -0000110101010011 0000100001000000010100010100000000101000 -0000110101010111 0000110010000000010100010100000000101000 -0000110101011011 0001110000000000010100010100000000101000 -0000110110010100 0000010011000000100100010100000000101000 -0000110110011000 0001010001000000100100010100000000101000 -0000110110011100 0000100001000000100100010100000000101000 -0000110110010001 0000010011000000100100010100000000101000 -0000110110011001 0001010010000000100100010100000000101000 -0000110110011101 0000110010000000100100010100000000101000 -0000110110010010 0001010001000000100100010100000000101000 -0000110110010110 0001010010000000100100010100000000101000 -0000110110011110 0001110000000000100100010100000000101000 -0000110110010011 0000100001000000100100010100000000101000 -0000110110010111 0000110010000000100100010100000000101000 -0000110110011011 0001110000000000100100010100000000101000 -0000110100010100 0000010011000000000100010100000000101000 -0000110100011000 0001010001000000000100010100000000101000 -0000110100011100 0000100001000000000100010100000000101000 -0000110100010001 0000010011000000000100010100000000101000 -0000110100011001 0001010010000000000100010100000000101000 -0000110100011101 0000110010000000000100010100000000101000 -0000110100010010 0001010001000000000100010100000000101000 -0000110100010110 0001010010000000000100010100000000101000 -0000110100011110 0001110000000000000100010100000000101000 -0000110100010011 0000100001000000000100010100000000101000 -0000110100010111 0000110010000000000100010100000000101000 -0000110100011011 0001110000000000000100010100000000101000 -0000110111010100 0000010011000000110100010100000000101000 -0000110111011000 0001010001000000110100010100000000101000 -0000110111011100 0000100001000000110100010100000000101000 -0000110111010001 0000010011000000110100010100000000101000 -0000110111011001 0001010010000000110100010100000000101000 -0000110111011101 0000110010000000110100010100000000101000 -0000110111010010 0001010001000000110100010100000000101000 -0000110111010110 0001010010000000110100010100000000101000 -0000110111011110 0001110000000000110100010100000000101000 -0000110111010011 0000100001000000110100010100000000101000 -0000110111010111 0000110010000000110100010100000000101000 -0000110111011011 0001110000000000110100010100000000101000 -0000110101000100 0000010011000000010000010100000000101000 -0000110101001000 0001010001000000010000010100000000101000 -0000110101001100 0000100001000000010000010100000000101000 -0000110101000001 0000010011000000010000010100000000101000 -0000110101001001 0001010010000000010000010100000000101000 -0000110101001101 0000110010000000010000010100000000101000 -0000110101000010 0001010001000000010000010100000000101000 -0000110101000110 0001010010000000010000010100000000101000 -0000110101001110 0001110000000000010000010100000000101000 -0000110101000011 0000100001000000010000010100000000101000 -0000110101000111 0000110010000000010000010100000000101000 -0000110101001011 0001110000000000010000010100000000101000 -0000110110000100 0000010011000000100000010100000000101000 -0000110110001000 0001010001000000100000010100000000101000 -0000110110001100 0000100001000000100000010100000000101000 -0000110110000001 0000010011000000100000010100000000101000 -0000110110001001 0001010010000000100000010100000000101000 -0000110110001101 0000110010000000100000010100000000101000 -0000110110000010 0001010001000000100000010100000000101000 -0000110110000110 0001010010000000100000010100000000101000 -0000110110001110 0001110000000000100000010100000000101000 -0000110110000011 0000100001000000100000010100000000101000 -0000110110000111 0000110010000000100000010100000000101000 -0000110110001011 0001110000000000100000010100000000101000 -0000110100000100 0000010011000000000000010100000000101000 -0000110100001000 0001010001000000000000010100000000101000 -0000110100001100 0000100001000000000000010100000000101000 -0000110100000001 0000010011000000000000010100000000101000 -0000110100001001 0001010010000000000000010100000000101000 -0000110100001101 0000110010000000000000010100000000101000 -0000110100000010 0001010001000000000000010100000000101000 -0000110100000110 0001010010000000000000010100000000101000 -0000110100001110 0001110000000000000000010100000000101000 -0000110100000011 0000100001000000000000010100000000101000 -0000110100000111 0000110010000000000000010100000000101000 -0000110100001011 0001110000000000000000010100000000101000 -0000110111000100 0000010011000000110000010100000000101000 -0000110111001000 0001010001000000110000010100000000101000 -0000110111001100 0000100001000000110000010100000000101000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000110111000001 0000010011000000110000010100000000101000 -0000110111001001 0001010010000000110000010100000000101000 -0000110111001101 0000110010000000110000010100000000101000 -0000110111000010 0001010001000000110000010100000000101000 -0000110111000110 0001010010000000110000010100000000101000 -0000110111001110 0001110000000000110000010100000000101000 -0000110111000011 0000100001000000110000010100000000101000 -0000110111000111 0000110010000000110000010100000000101000 -0000110111001011 0001110000000000110000010100000000101000 -0000110101110100 0000010011000000011100010100000000101000 -0000110101111000 0001010001000000011100010100000000101000 -0000110101111100 0000100001000000011100010100000000101000 -0000110101110001 0000010011000000011100010100000000101000 -0000110101111001 0001010010000000011100010100000000101000 -0000110101111101 0000110010000000011100010100000000101000 -0000110101110010 0001010001000000011100010100000000101000 -0000110101110110 0001010010000000011100010100000000101000 -0000110101111110 0001110000000000011100010100000000101000 -0000110101110011 0000100001000000011100010100000000101000 -0000110101110111 0000110010000000011100010100000000101000 -0000110101111011 0001110000000000011100010100000000101000 -0000110110110100 0000010011000000101100010100000000101000 -0000110110111000 0001010001000000101100010100000000101000 -0000110110111100 0000100001000000101100010100000000101000 -0000110110110001 0000010011000000101100010100000000101000 -0000110110111001 0001010010000000101100010100000000101000 -0000110110111101 0000110010000000101100010100000000101000 -0000110110110010 0001010001000000101100010100000000101000 -0000110110110110 0001010010000000101100010100000000101000 -0000110110111110 0001110000000000101100010100000000101000 -0000110110110011 0000100001000000101100010100000000101000 -0000110110110111 0000110010000000101100010100000000101000 -0000110110111011 0001110000000000101100010100000000101000 -0000110100110100 0000010011000000001100010100000000101000 -0000110100111000 0001010001000000001100010100000000101000 -0000110100111100 0000100001000000001100010100000000101000 -0000110100110001 0000010011000000001100010100000000101000 -0000110100111001 0001010010000000001100010100000000101000 -0000110100111101 0000110010000000001100010100000000101000 -0000110100110010 0001010001000000001100010100000000101000 -0000110100110110 0001010010000000001100010100000000101000 -0000110100111110 0001110000000000001100010100000000101000 -0000110100110011 0000100001000000001100010100000000101000 -0000110100110111 0000110010000000001100010100000000101000 -0000110100111011 0001110000000000001100010100000000101000 -0000110111110100 0000010011000000111100010100000000101000 -0000110111111000 0001010001000000111100010100000000101000 -0000110111111100 0000100001000000111100010100000000101000 -0000110111110001 0000010011000000111100010100000000101000 -0000110111111001 0001010010000000111100010100000000101000 -0000110111111101 0000110010000000111100010100000000101000 -0000110111110010 0001010001000000111100010100000000101000 -0000110111110110 0001010010000000111100010100000000101000 -0000110111111110 0001110000000000111100010100000000101000 -0000110111110011 0000100001000000111100010100000000101000 -0000110111110111 0000110010000000111100010100000000101000 -0000110111111011 0001110000000000111100010100000000101000 -0000010001000000 0000000001000000010011000000000000000000 -0000010010000101 0000010010000000100011000000000000000000 -0000010001000101 0000010010000000010011000000000000000000 -0000010001001010 0001010000000000010011000000000000000000 -0000010001001111 0000100000000000010011000000000000000000 -0000010010000000 0000000001000000100011000000000000000000 -0000010010001010 0001010000000000100011000000000000000000 -0000010010001111 0000100000000000100011000000000000000000 -0000010001000100 0000010011000000010011000000000000000000 -0000010001001000 0001010001000000010011000000000000000000 -0000010001001100 0000100001000000010011000000000000000000 -0000010001000001 0000010011000000010011000000000000000000 -0000010001001001 0001010010000000010011000000000000000000 -0000010001001101 0000110010000000010011000000000000000000 -0000010001000010 0001010001000000010011000000000000000000 -0000010001000110 0001010010000000010011000000000000000000 -0000010001001110 0001110000000000010011000000000000000000 -0000010001000011 0000100001000000010011000000000000000000 -0000010001000111 0000110010000000010011000000000000000000 -0000010001001011 0001110000000000010011000000000000000000 -0000010010000100 0000010011000000100011000000000000000000 -0000010010001000 0001010001000000100011000000000000000000 -0000010010001100 0000100001000000100011000000000000000000 -0000010010000001 0000010011000000100011000000000000000000 -0000010010001001 0001010010000000100011000000000000000000 -0000010010001101 0000110010000000100011000000000000000000 -0000010010000010 0001010001000000100011000000000000000000 -0000010010000110 0001010010000000100011000000000000000000 -0000010010001110 0001110000000000100011000000000000000000 -0000010010000011 0000100001000000100011000000000000000000 -0000010010000111 0000110010000000100011000000000000000000 -0000010010001011 0001110000000000100011000000000000000000 -000001010100---- 0001010000000000010011000000000000000000 -000001011000---- 0001010000000000100011000000000000000000 -0000010001100000 0000000001000000011011000000000000000000 -0000010001100101 0000010010000000011011000000000000000000 -0000010001101010 0001010000000000011011000000000000000000 -0000010001101111 0000100000000000011011000000000000000000 -0000010010100000 0000000001000000101011000000000000000000 -0000010010100101 0000010010000000101011000000000000000000 -0000010010101010 0001010000000000101011000000000000000000 -0000010010101111 0000100000000000101011000000000000000000 -0000010000100000 0000000001000000001011000000000000000000 -0000010000100101 0000010010000000001011000000000000000000 -0000010000101010 0001010000000000001011000000000000000000 -0000010000101111 0000100000000000001011000000000000000000 -0000010011100000 0000000001000000111011000000000000000000 -0000010011100101 0000010010000000111011000000000000000000 -0000010011101010 0001010000000000111011000000000000000000 -0000010011101111 0000100000000000111011000000000000000000 -0000010001010000 0000000001000000010111000000000000000000 -0000010001010101 0000010010000000010111000000000000000000 -0000010001011010 0001010000000000010111000000000000000000 -0000010001011111 0000100000000000010111000000000000000000 -0000010010010000 0000000001000000100111000000000000000000 -0000010010010101 0000010010000000100111000000000000000000 -0000010010011010 0001010000000000100111000000000000000000 -0000010010011111 0000100000000000100111000000000000000000 -0000010000010000 0000000001000000000111000000000000000000 -0000010000010101 0000010010000000000111000000000000000000 -0000010000011010 0001010000000000000111000000000000000000 -0000010000011111 0000100000000000000111000000000000000000 -0000010011010000 0000000001000000110111000000000000000000 -0000010011010101 0000010010000000110111000000000000000000 -0000010011011010 0001010000000000110111000000000000000000 -0000010011011111 0000100000000000110111000000000000000000 -0000010001000000 0000000001000000010011000000000000000000 -0000010001000101 0000010010000000010011000000000000000000 -0000010001001010 0001010000000000010011000000000000000000 -0000010001001111 0000100000000000010011000000000000000000 -0000010010000000 0000000001000000100011000000000000000000 -0000010010000101 0000010010000000100011000000000000000000 -0000010010001010 0001010000000000100011000000000000000000 -0000010010001111 0000100000000000100011000000000000000000 -0000010000000000 0000000001000000000011000000000000000000 -0000010000000101 0000010010000000000011000000000000000000 -0000010000001010 0001010000000000000011000000000000000000 -0000010000001111 0000100000000000000011000000000000000000 -0000010011000000 0000000001000000110011000000000000000000 -0000010011000101 0000010010000000110011000000000000000000 -0000010011001010 0001010000000000110011000000000000000000 -0000010011001111 0000100000000000110011000000000000000000 -0000010001110000 0000000001000000011111000000000000000000 -0000010001110101 0000010010000000011111000000000000000000 -0000010001111010 0001010000000000011111000000000000000000 -0000010001111111 0000100000000000011111000000000000000000 -0000010010110000 0000000001000000101111000000000000000000 -0000010010110101 0000010010000000101111000000000000000000 -0000010010111010 0001010000000000101111000000000000000000 -0000010010111111 0000100000000000101111000000000000000000 -0000010000110000 0000000001000000001111000000000000000000 -0000010000110101 0000010010000000001111000000000000000000 -0000010000111010 0001010000000000001111000000000000000000 -0000010000111111 0000100000000000001111000000000000000000 -0000010011110000 0000000001000000111111000000000000000000 -0000010011110101 0000010010000000111111000000000000000000 -0000010011111010 0001010000000000111111000000000000000000 -0000010011111111 0000100000000000111111000000000000000000 -0000010001100100 0000010011000000011011000000000000000000 -0000010001101000 0001010001000000011011000000000000000000 -0000010001101100 0000100001000000011011000000000000000000 -0000010001100001 0000010011000000011011000000000000000000 -0000010001101001 0001010010000000011011000000000000000000 -0000010001101101 0000110010000000011011000000000000000000 -0000010001100010 0001010001000000011011000000000000000000 -0000010001100110 0001010010000000011011000000000000000000 -0000010001101110 0001110000000000011011000000000000000000 -0000010001100011 0000100001000000011011000000000000000000 -0000010001100111 0000110010000000011011000000000000000000 -0000010001101011 0001110000000000011011000000000000000000 -0000010010100100 0000010011000000101011000000000000000000 -0000010010101000 0001010001000000101011000000000000000000 -0000010010101100 0000100001000000101011000000000000000000 -0000010010100001 0000010011000000101011000000000000000000 -0000010010101001 0001010010000000101011000000000000000000 -0000010010101101 0000110010000000101011000000000000000000 -0000010010100010 0001010001000000101011000000000000000000 -0000010010100110 0001010010000000101011000000000000000000 -0000010010101110 0001110000000000101011000000000000000000 -0000010010100011 0000100001000000101011000000000000000000 -0000010010100111 0000110010000000101011000000000000000000 -0000010010101011 0001110000000000101011000000000000000000 -0000010000100100 0000010011000000001011000000000000000000 -0000010000101000 0001010001000000001011000000000000000000 -0000010000101100 0000100001000000001011000000000000000000 -0000010000100001 0000010011000000001011000000000000000000 -0000010000101001 0001010010000000001011000000000000000000 -0000010000101101 0000110010000000001011000000000000000000 -0000010000100010 0001010001000000001011000000000000000000 -0000010000100110 0001010010000000001011000000000000000000 -0000010000101110 0001110000000000001011000000000000000000 -0000010000100011 0000100001000000001011000000000000000000 -0000010000100111 0000110010000000001011000000000000000000 -0000010000101011 0001110000000000001011000000000000000000 -0000010011100100 0000010011000000111011000000000000000000 -0000010011101000 0001010001000000111011000000000000000000 -0000010011101100 0000100001000000111011000000000000000000 -0000010011100001 0000010011000000111011000000000000000000 -0000010011101001 0001010010000000111011000000000000000000 -0000010011101101 0000110010000000111011000000000000000000 -0000010011100010 0001010001000000111011000000000000000000 -0000010011100110 0001010010000000111011000000000000000000 -0000010011101110 0001110000000000111011000000000000000000 -0000010011100011 0000100001000000111011000000000000000000 -0000010011100111 0000110010000000111011000000000000000000 -0000010011101011 0001110000000000111011000000000000000000 -0000010001010100 0000010011000000010111000000000000000000 -0000010001011000 0001010001000000010111000000000000000000 -0000010001011100 0000100001000000010111000000000000000000 -0000010001010001 0000010011000000010111000000000000000000 -0000010001011001 0001010010000000010111000000000000000000 -0000010001011101 0000110010000000010111000000000000000000 -0000010001010010 0001010001000000010111000000000000000000 -0000010001010110 0001010010000000010111000000000000000000 -0000010001011110 0001110000000000010111000000000000000000 -0000010001010011 0000100001000000010111000000000000000000 -0000010001010111 0000110010000000010111000000000000000000 -0000010001011011 0001110000000000010111000000000000000000 -0000010010010100 0000010011000000100111000000000000000000 -0000010010011000 0001010001000000100111000000000000000000 -0000010010011100 0000100001000000100111000000000000000000 -0000010010010001 0000010011000000100111000000000000000000 -0000010010011001 0001010010000000100111000000000000000000 -0000010010011101 0000110010000000100111000000000000000000 -0000010010010010 0001010001000000100111000000000000000000 -0000010010010110 0001010010000000100111000000000000000000 -0000010010011110 0001110000000000100111000000000000000000 -0000010010010011 0000100001000000100111000000000000000000 -0000010010010111 0000110010000000100111000000000000000000 -0000010010011011 0001110000000000100111000000000000000000 -0000010000010100 0000010011000000000111000000000000000000 -0000010000011000 0001010001000000000111000000000000000000 -0000010000011100 0000100001000000000111000000000000000000 -0000010000010001 0000010011000000000111000000000000000000 -0000010000011001 0001010010000000000111000000000000000000 -0000010000011101 0000110010000000000111000000000000000000 -0000010000010010 0001010001000000000111000000000000000000 -0000010000010110 0001010010000000000111000000000000000000 -0000010000011110 0001110000000000000111000000000000000000 -0000010000010011 0000100001000000000111000000000000000000 -0000010000010111 0000110010000000000111000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000010000011011 0001110000000000000111000000000000000000 -0000010011010100 0000010011000000110111000000000000000000 -0000010011011000 0001010001000000110111000000000000000000 -0000010011011100 0000100001000000110111000000000000000000 -0000010011010001 0000010011000000110111000000000000000000 -0000010011011001 0001010010000000110111000000000000000000 -0000010011011101 0000110010000000110111000000000000000000 -0000010011010010 0001010001000000110111000000000000000000 -0000010011010110 0001010010000000110111000000000000000000 -0000010011011110 0001110000000000110111000000000000000000 -0000010011010011 0000100001000000110111000000000000000000 -0000010011010111 0000110010000000110111000000000000000000 -0000010011011011 0001110000000000110111000000000000000000 -0000010001000100 0000010011000000010011000000000000000000 -0000010001001000 0001010001000000010011000000000000000000 -0000010001001100 0000100001000000010011000000000000000000 -0000010001000001 0000010011000000010011000000000000000000 -0000010001001001 0001010010000000010011000000000000000000 -0000010001001101 0000110010000000010011000000000000000000 -0000010001000010 0001010001000000010011000000000000000000 -0000010001000110 0001010010000000010011000000000000000000 -0000010001001110 0001110000000000010011000000000000000000 -0000010001000011 0000100001000000010011000000000000000000 -0000010001000111 0000110010000000010011000000000000000000 -0000010001001011 0001110000000000010011000000000000000000 -0000010010000100 0000010011000000100011000000000000000000 -0000010010001000 0001010001000000100011000000000000000000 -0000010010001100 0000100001000000100011000000000000000000 -0000010010000001 0000010011000000100011000000000000000000 -0000010010001001 0001010010000000100011000000000000000000 -0000010010001101 0000110010000000100011000000000000000000 -0000010010000010 0001010001000000100011000000000000000000 -0000010010000110 0001010010000000100011000000000000000000 -0000010010001110 0001110000000000100011000000000000000000 -0000010010000011 0000100001000000100011000000000000000000 -0000010010000111 0000110010000000100011000000000000000000 -0000010010001011 0001110000000000100011000000000000000000 -0000010000000100 0000010011000000000011000000000000000000 -0000010000001000 0001010001000000000011000000000000000000 -0000010000001100 0000100001000000000011000000000000000000 -0000010000000001 0000010011000000000011000000000000000000 -0000010000001001 0001010010000000000011000000000000000000 -0000010000001101 0000110010000000000011000000000000000000 -0000010000000010 0001010001000000000011000000000000000000 -0000010000000110 0001010010000000000011000000000000000000 -0000010000001110 0001110000000000000011000000000000000000 -0000010000000011 0000100001000000000011000000000000000000 -0000010000000111 0000110010000000000011000000000000000000 -0000010000001011 0001110000000000000011000000000000000000 -0000010011000100 0000010011000000110011000000000000000000 -0000010011001000 0001010001000000110011000000000000000000 -0000010011001100 0000100001000000110011000000000000000000 -0000010011000001 0000010011000000110011000000000000000000 -0000010011001001 0001010010000000110011000000000000000000 -0000010011001101 0000110010000000110011000000000000000000 -0000010011000010 0001010001000000110011000000000000000000 -0000010011000110 0001010010000000110011000000000000000000 -0000010011001110 0001110000000000110011000000000000000000 -0000010011000011 0000100001000000110011000000000000000000 -0000010011000111 0000110010000000110011000000000000000000 -0000010011001011 0001110000000000110011000000000000000000 -0000010001110100 0000010011000000011111000000000000000000 -0000010001111000 0001010001000000011111000000000000000000 -0000010001111100 0000100001000000011111000000000000000000 -0000010001110001 0000010011000000011111000000000000000000 -0000010001111001 0001010010000000011111000000000000000000 -0000010001111101 0000110010000000011111000000000000000000 -0000010001110010 0001010001000000011111000000000000000000 -0000010001110110 0001010010000000011111000000000000000000 -0000010001111110 0001110000000000011111000000000000000000 -0000010001110011 0000100001000000011111000000000000000000 -0000010001110111 0000110010000000011111000000000000000000 -0000010001111011 0001110000000000011111000000000000000000 -0000010010110100 0000010011000000101111000000000000000000 -0000010010111000 0001010001000000101111000000000000000000 -0000010010111100 0000100001000000101111000000000000000000 -0000010010110001 0000010011000000101111000000000000000000 -0000010010111001 0001010010000000101111000000000000000000 -0000010010111101 0000110010000000101111000000000000000000 -0000010010110010 0001010001000000101111000000000000000000 -0000010010110110 0001010010000000101111000000000000000000 -0000010010111110 0001110000000000101111000000000000000000 -0000010010110011 0000100001000000101111000000000000000000 -0000010010110111 0000110010000000101111000000000000000000 -0000010010111011 0001110000000000101111000000000000000000 -0000010000110100 0000010011000000001111000000000000000000 -0000010000111000 0001010001000000001111000000000000000000 -0000010000111100 0000100001000000001111000000000000000000 -0000010000110001 0000010011000000001111000000000000000000 -0000010000111001 0001010010000000001111000000000000000000 -0000010000111101 0000110010000000001111000000000000000000 -0000010000110010 0001010001000000001111000000000000000000 -0000010000110110 0001010010000000001111000000000000000000 -0000010000111110 0001110000000000001111000000000000000000 -0000010000110011 0000100001000000001111000000000000000000 -0000010000110111 0000110010000000001111000000000000000000 -0000010000111011 0001110000000000001111000000000000000000 -0000010011110100 0000010011000000111111000000000000000000 -0000010011111000 0001010001000000111111000000000000000000 -0000010011111100 0000100001000000111111000000000000000000 -0000010011110001 0000010011000000111111000000000000000000 -0000010011111001 0001010010000000111111000000000000000000 -0000010011111101 0000110010000000111111000000000000000000 -0000010011110010 0001010001000000111111000000000000000000 -0000010011110110 0001010010000000111111000000000000000000 -0000010011111110 0001110000000000111111000000000000000000 -0000010011110011 0000100001000000111111000000000000000000 -0000010011110111 0000110010000000111111000000000000000000 -0000010011111011 0001110000000000111111000000000000000000 -000001010110---- 0001010000000000011011000000000000000000 -000001011010---- 0001010000000000101011000000000000000000 -000001010101---- 0000100000000000010111000000000000000000 -000001011001---- 0000100000000000100111000000000000000000 -000001010100---- 0001010000000000010011000000000000000000 -000001011000---- 0001010000000000100011000000000000000000 -000001010111---- 0000100000000000011111000000000000000000 -000001011011---- 0000100000000000101111000000000000000000 -0000111101100000 0000000001100000011000010100000000101000 -0000111101100101 0000010010100000011000010100000000101000 -0000111101101010 0001010000100000011000010100000000101000 -0000111101101111 0000100000100000011000010100000000101000 -0000111110100000 0000000001100000101000010100000000101000 -0000111110100101 0000010010100000101000010100000000101000 -0000111110101010 0001010000100000101000010100000000101000 -0000111110101111 0000100000100000101000010100000000101000 -0000111100100000 0000000001100000001000010100000000101000 -0000111100100101 0000010010100000001000010100000000101000 -0000111100101010 0001010000100000001000010100000000101000 -0000111100101111 0000100000100000001000010100000000101000 -0000111111100000 0000000001100000111000010100000000101000 -0000111111100101 0000010010100000111000010100000000101000 -0000111111101010 0001010000100000111000010100000000101000 -0000111111101111 0000100000100000111000010100000000101000 -0000111101010000 0000000001100000010100010100000000101000 -0000111101010101 0000010010100000010100010100000000101000 -0000111101011010 0001010000100000010100010100000000101000 -0000111101011111 0000100000100000010100010100000000101000 -0000111110010000 0000000001100000100100010100000000101000 -0000111110010101 0000010010100000100100010100000000101000 -0000111110011010 0001010000100000100100010100000000101000 -0000111110011111 0000100000100000100100010100000000101000 -0000111100010000 0000000001100000000100010100000000101000 -0000111100010101 0000010010100000000100010100000000101000 -0000111100011010 0001010000100000000100010100000000101000 -0000111100011111 0000100000100000000100010100000000101000 -0000111111010000 0000000001100000110100010100000000101000 -0000111111010101 0000010010100000110100010100000000101000 -0000111111011010 0001010000100000110100010100000000101000 -0000111111011111 0000100000100000110100010100000000101000 -0000111101000000 0000000001100000010000010100000000101000 -0000111101000101 0000010010100000010000010100000000101000 -0000111101001010 0001010000100000010000010100000000101000 -0000111101001111 0000100000100000010000010100000000101000 -0000111110000000 0000000001100000100000010100000000101000 -0000111110000101 0000010010100000100000010100000000101000 -0000111110001010 0001010000100000100000010100000000101000 -0000111110001111 0000100000100000100000010100000000101000 -0000111100000000 0000000001100000000000010100000000101000 -0000111100000101 0000010010100000000000010100000000101000 -0000111100001010 0001010000100000000000010100000000101000 -0000111100001111 0000100000100000000000010100000000101000 -0000111111000000 0000000001100000110000010100000000101000 -0000111111000101 0000010010100000110000010100000000101000 -0000111111001010 0001010000100000110000010100000000101000 -0000111111001111 0000100000100000110000010100000000101000 -0000111101110000 0000000001100000011100010100000000101000 -0000111101110101 0000010010100000011100010100000000101000 -0000111101111010 0001010000100000011100010100000000101000 -0000111101111111 0000100000100000011100010100000000101000 -0000111110110000 0000000001100000101100010100000000101000 -0000111110110101 0000010010100000101100010100000000101000 -0000111110111010 0001010000100000101100010100000000101000 -0000111110111111 0000100000100000101100010100000000101000 -0000111100110000 0000000001100000001100010100000000101000 -0000111100110101 0000010010100000001100010100000000101000 -0000111100111010 0001010000100000001100010100000000101000 -0000111100111111 0000100000100000001100010100000000101000 -0000111111110000 0000000001100000111100010100000000101000 -0000111111110101 0000010010100000111100010100000000101000 -0000111111111010 0001010000100000111100010100000000101000 -0000111111111111 0000100000100000111100010100000000101000 -0000111101100100 0000010011100000011000010100000000101000 -0000111101101000 0001010001100000011000010100000000101000 -0000111101101100 0000100001100000011000010100000000101000 -0000111101100001 0000010011100000011000010100000000101000 -0000111101101001 0001010010100000011000010100000000101000 -0000111101101101 0000110010100000011000010100000000101000 -0000111101100010 0001010001100000011000010100000000101000 -0000111101100110 0001010010100000011000010100000000101000 -0000111101101110 0001110000100000011000010100000000101000 -0000111101100011 0000100001100000011000010100000000101000 -0000111101100111 0000110010100000011000010100000000101000 -0000111101101011 0001110000100000011000010100000000101000 -0000111110100100 0000010011100000101000010100000000101000 -0000111110101000 0001010001100000101000010100000000101000 -0000111110101100 0000100001100000101000010100000000101000 -0000111110100001 0000010011100000101000010100000000101000 -0000111110101001 0001010010100000101000010100000000101000 -0000111110101101 0000110010100000101000010100000000101000 -0000111110100010 0001010001100000101000010100000000101000 -0000111110100110 0001010010100000101000010100000000101000 -0000111110101110 0001110000100000101000010100000000101000 -0000111110100011 0000100001100000101000010100000000101000 -0000111110100111 0000110010100000101000010100000000101000 -0000111110101011 0001110000100000101000010100000000101000 -0000111100100100 0000010011100000001000010100000000101000 -0000111100101000 0001010001100000001000010100000000101000 -0000111100101100 0000100001100000001000010100000000101000 -0000111100100001 0000010011100000001000010100000000101000 -0000111100101001 0001010010100000001000010100000000101000 -0000111100101101 0000110010100000001000010100000000101000 -0000111100100010 0001010001100000001000010100000000101000 -0000111100100110 0001010010100000001000010100000000101000 -0000111100101110 0001110000100000001000010100000000101000 -0000111100100011 0000100001100000001000010100000000101000 -0000111100100111 0000110010100000001000010100000000101000 -0000111100101011 0001110000100000001000010100000000101000 -0000111111100100 0000010011100000111000010100000000101000 -0000111111101000 0001010001100000111000010100000000101000 -0000111111101100 0000100001100000111000010100000000101000 -0000111111100001 0000010011100000111000010100000000101000 -0000111111101001 0001010010100000111000010100000000101000 -0000111111101101 0000110010100000111000010100000000101000 -0000111111100010 0001010001100000111000010100000000101000 -0000111111100110 0001010010100000111000010100000000101000 -0000111111101110 0001110000100000111000010100000000101000 -0000111111100011 0000100001100000111000010100000000101000 -0000111111100111 0000110010100000111000010100000000101000 -0000111111101011 0001110000100000111000010100000000101000 -0000111101010100 0000010011100000010100010100000000101000 -0000111101011000 0001010001100000010100010100000000101000 -0000111101011100 0000100001100000010100010100000000101000 -0000111101010001 0000010011100000010100010100000000101000 -0000111101011001 0001010010100000010100010100000000101000 -0000111101011101 0000110010100000010100010100000000101000 -0000111101010010 0001010001100000010100010100000000101000 -0000111101010110 0001010010100000010100010100000000101000 -0000111101011110 0001110000100000010100010100000000101000 -0000111101010011 0000100001100000010100010100000000101000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000111101010111 0000110010100000010100010100000000101000 -0000111101011011 0001110000100000010100010100000000101000 -0000111110010100 0000010011100000100100010100000000101000 -0000111110011000 0001010001100000100100010100000000101000 -0000111110011100 0000100001100000100100010100000000101000 -0000111110010001 0000010011100000100100010100000000101000 -0000111110011001 0001010010100000100100010100000000101000 -0000111110011101 0000110010100000100100010100000000101000 -0000111110010010 0001010001100000100100010100000000101000 -0000111110010110 0001010010100000100100010100000000101000 -0000111110011110 0001110000100000100100010100000000101000 -0000111110010011 0000100001100000100100010100000000101000 -0000111110010111 0000110010100000100100010100000000101000 -0000111110011011 0001110000100000100100010100000000101000 -0000111100010100 0000010011100000000100010100000000101000 -0000111100011000 0001010001100000000100010100000000101000 -0000111100011100 0000100001100000000100010100000000101000 -0000111100010001 0000010011100000000100010100000000101000 -0000111100011001 0001010010100000000100010100000000101000 -0000111100011101 0000110010100000000100010100000000101000 -0000111100010010 0001010001100000000100010100000000101000 -0000111100010110 0001010010100000000100010100000000101000 -0000111100011110 0001110000100000000100010100000000101000 -0000111100010011 0000100001100000000100010100000000101000 -0000111100010111 0000110010100000000100010100000000101000 -0000111100011011 0001110000100000000100010100000000101000 -0000111111010100 0000010011100000110100010100000000101000 -0000111111011000 0001010001100000110100010100000000101000 -0000111111011100 0000100001100000110100010100000000101000 -0000111111010001 0000010011100000110100010100000000101000 -0000111111011001 0001010010100000110100010100000000101000 -0000111111011101 0000110010100000110100010100000000101000 -0000111111010010 0001010001100000110100010100000000101000 -0000111111010110 0001010010100000110100010100000000101000 -0000111111011110 0001110000100000110100010100000000101000 -0000111111010011 0000100001100000110100010100000000101000 -0000111111010111 0000110010100000110100010100000000101000 -0000111111011011 0001110000100000110100010100000000101000 -0000111101000100 0000010011100000010000010100000000101000 -0000111101001000 0001010001100000010000010100000000101000 -0000111101001100 0000100001100000010000010100000000101000 -0000111101000001 0000010011100000010000010100000000101000 -0000111101001001 0001010010100000010000010100000000101000 -0000111101001101 0000110010100000010000010100000000101000 -0000111101000010 0001010001100000010000010100000000101000 -0000111101000110 0001010010100000010000010100000000101000 -0000111101001110 0001110000100000010000010100000000101000 -0000111101000011 0000100001100000010000010100000000101000 -0000111101000111 0000110010100000010000010100000000101000 -0000111101001011 0001110000100000010000010100000000101000 -0000111110000100 0000010011100000100000010100000000101000 -0000111110001000 0001010001100000100000010100000000101000 -0000111110001100 0000100001100000100000010100000000101000 -0000111110000001 0000010011100000100000010100000000101000 -0000111110001001 0001010010100000100000010100000000101000 -0000111110001101 0000110010100000100000010100000000101000 -0000111110000010 0001010001100000100000010100000000101000 -0000111110000110 0001010010100000100000010100000000101000 -0000111110001110 0001110000100000100000010100000000101000 -0000111110000011 0000100001100000100000010100000000101000 -0000111110000111 0000110010100000100000010100000000101000 -0000111110001011 0001110000100000100000010100000000101000 -0000111100000100 0000010011100000000000010100000000101000 -0000111100001000 0001010001100000000000010100000000101000 -0000111100001100 0000100001100000000000010100000000101000 -0000111100000001 0000010011100000000000010100000000101000 -0000111100001001 0001010010100000000000010100000000101000 -0000111100001101 0000110010100000000000010100000000101000 -0000111100000010 0001010001100000000000010100000000101000 -0000111100000110 0001010010100000000000010100000000101000 -0000111100001110 0001110000100000000000010100000000101000 -0000111100000011 0000100001100000000000010100000000101000 -0000111100000111 0000110010100000000000010100000000101000 -0000111100001011 0001110000100000000000010100000000101000 -0000111111000100 0000010011100000110000010100000000101000 -0000111111001000 0001010001100000110000010100000000101000 -0000111111001100 0000100001100000110000010100000000101000 -0000111111000001 0000010011100000110000010100000000101000 -0000111111001001 0001010010100000110000010100000000101000 -0000111111001101 0000110010100000110000010100000000101000 -0000111111000010 0001010001100000110000010100000000101000 -0000111111000110 0001010010100000110000010100000000101000 -0000111111001110 0001110000100000110000010100000000101000 -0000111111000011 0000100001100000110000010100000000101000 -0000111111000111 0000110010100000110000010100000000101000 -0000111111001011 0001110000100000110000010100000000101000 -0000111101110100 0000010011100000011100010100000000101000 -0000111101111000 0001010001100000011100010100000000101000 -0000111101111100 0000100001100000011100010100000000101000 -0000111101110001 0000010011100000011100010100000000101000 -0000111101111001 0001010010100000011100010100000000101000 -0000111101111101 0000110010100000011100010100000000101000 -0000111101110010 0001010001100000011100010100000000101000 -0000111101110110 0001010010100000011100010100000000101000 -0000111101111110 0001110000100000011100010100000000101000 -0000111101110011 0000100001100000011100010100000000101000 -0000111101110111 0000110010100000011100010100000000101000 -0000111101111011 0001110000100000011100010100000000101000 -0000111110110100 0000010011100000101100010100000000101000 -0000111110111000 0001010001100000101100010100000000101000 -0000111110111100 0000100001100000101100010100000000101000 -0000111110110001 0000010011100000101100010100000000101000 -0000111110111001 0001010010100000101100010100000000101000 -0000111110111101 0000110010100000101100010100000000101000 -0000111110110010 0001010001100000101100010100000000101000 -0000111110110110 0001010010100000101100010100000000101000 -0000111110111110 0001110000100000101100010100000000101000 -0000111110110011 0000100001100000101100010100000000101000 -0000111110110111 0000110010100000101100010100000000101000 -0000111110111011 0001110000100000101100010100000000101000 -0000111100110100 0000010011100000001100010100000000101000 -0000111100111000 0001010001100000001100010100000000101000 -0000111100111100 0000100001100000001100010100000000101000 -0000111100110001 0000010011100000001100010100000000101000 -0000111100111001 0001010010100000001100010100000000101000 -0000111100111101 0000110010100000001100010100000000101000 -0000111100110010 0001010001100000001100010100000000101000 -0000111100110110 0001010010100000001100010100000000101000 -0000111100111110 0001110000100000001100010100000000101000 -0000111100110011 0000100001100000001100010100000000101000 -0000111100110111 0000110010100000001100010100000000101000 -0000111100111011 0001110000100000001100010100000000101000 -0000111111110100 0000010011100000111100010100000000101000 -0000111111111000 0001010001100000111100010100000000101000 -0000111111111100 0000100001100000111100010100000000101000 -0000111111110001 0000010011100000111100010100000000101000 -0000111111111001 0001010010100000111100010100000000101000 -0000111111111101 0000110010100000111100010100000000101000 -0000111111110010 0001010001100000111100010100000000101000 -0000111111110110 0001010010100000111100010100000000101000 -0000111111111110 0001110000100000111100010100000000101000 -0000111111110011 0000100001100000111100010100000000101000 -0000111111110111 0000110010100000111100010100000000101000 -0000111111111011 0001110000100000111100010100000000101000 -0000100101100000 0000000001000100011000000000000000000000 -0000100101100101 0000010010000100011000000000000000000000 -0000100101101010 0001010000000100011000000000000000000000 -0000100101101111 0000100000000100011000000000000000000000 -0000100110100000 0000000001000100101000000000000000000000 -0000100110100101 0000010010000100101000000000000000000000 -0000100110101010 0001010000000100101000000000000000000000 -0000100110101111 0000100000000100101000000000000000000000 -0000100100100000 0000000001000100001000000000000000000000 -0000100100100101 0000010010000100001000000000000000000000 -0000100100101010 0001010000000100001000000000000000000000 -0000100100101111 0000100000000100001000000000000000000000 -0000100111100000 0000000001000100111000000000000000000000 -0000100111100101 0000010010000100111000000000000000000000 -0000100111101010 0001010000000100111000000000000000000000 -0000100111101111 0000100000000100111000000000000000000000 -0000100101010000 0000000001000100010100000000000000000000 -0000100101010101 0000010010000100010100000000000000000000 -0000100101011010 0001010000000100010100000000000000000000 -0000100101011111 0000100000000100010100000000000000000000 -0000100110010000 0000000001000100100100000000000000000000 -0000100110010101 0000010010000100100100000000000000000000 -0000100110011010 0001010000000100100100000000000000000000 -0000100110011111 0000100000000100100100000000000000000000 -0000100100010000 0000000001000100000100000000000000000000 -0000100100010101 0000010010000100000100000000000000000000 -0000100100011010 0001010000000100000100000000000000000000 -0000100100011111 0000100000000100000100000000000000000000 -0000100111010000 0000000001000100110100000000000000000000 -0000100111010101 0000010010000100110100000000000000000000 -0000100111011010 0001010000000100110100000000000000000000 -0000100111011111 0000100000000100110100000000000000000000 -0000100101000000 0000000001000100010000000000000000000000 -0000100101000101 0000010010000100010000000000000000000000 -0000100101001010 0001010000000100010000000000000000000000 -0000100101001111 0000100000000100010000000000000000000000 -0000100110000000 0000000001000100100000000000000000000000 -0000100110000101 0000010010000100100000000000000000000000 -0000100110001010 0001010000000100100000000000000000000000 -0000100110001111 0000100000000100100000000000000000000000 -0000100100000000 0000000001000100000000000000000000000000 -0000100100000101 0000010010000100000000000000000000000000 -0000100100001010 0001010000000100000000000000000000000000 -0000100100001111 0000100000000100000000000000000000000000 -0000100111000000 0000000001000100110000000000000000000000 -0000100111000101 0000010010000100110000000000000000000000 -0000100111001010 0001010000000100110000000000000000000000 -0000100111001111 0000100000000100110000000000000000000000 -0000100101110000 0000000001000100011100000000000000000000 -0000100101110101 0000010010000100011100000000000000000000 -0000100101111010 0001010000000100011100000000000000000000 -0000100101111111 0000100000000100011100000000000000000000 -0000100110110000 0000000001000100101100000000000000000000 -0000100110110101 0000010010000100101100000000000000000000 -0000100110111010 0001010000000100101100000000000000000000 -0000100110111111 0000100000000100101100000000000000000000 -0000100100110000 0000000001000100001100000000000000000000 -0000100100110101 0000010010000100001100000000000000000000 -0000100100111010 0001010000000100001100000000000000000000 -0000100100111111 0000100000000100001100000000000000000000 -0000100111110000 0000000001000100111100000000000000000000 -0000100111110101 0000010010000100111100000000000000000000 -0000100111111010 0001010000000100111100000000000000000000 -0000100111111111 0000100000000100111100000000000000000000 -0000100101100100 0000010011000100011000000000000000000000 -0000100101101000 0001010001000100011000000000000000000000 -0000100101101100 0000100001000100011000000000000000000000 -0000100101100001 0000010011000100011000000000000000000000 -0000100101101001 0001010010000100011000000000000000000000 -0000100101101101 0000110010000100011000000000000000000000 -0000100101100010 0001010001000100011000000000000000000000 -0000100101100110 0001010010000100011000000000000000000000 -0000100101101110 0001110000000100011000000000000000000000 -0000100101100011 0000100001000100011000000000000000000000 -0000100101100111 0000110010000100011000000000000000000000 -0000100101101011 0001110000000100011000000000000000000000 -0000100110100100 0000010011000100101000000000000000000000 -0000100110101000 0001010001000100101000000000000000000000 -0000100110101100 0000100001000100101000000000000000000000 -0000100110100001 0000010011000100101000000000000000000000 -0000100110101001 0001010010000100101000000000000000000000 -0000100110101101 0000110010000100101000000000000000000000 -0000100110100010 0001010001000100101000000000000000000000 -0000100110100110 0001010010000100101000000000000000000000 -0000100110101110 0001110000000100101000000000000000000000 -0000100110100011 0000100001000100101000000000000000000000 -0000100110100111 0000110010000100101000000000000000000000 -0000100110101011 0001110000000100101000000000000000000000 -0000100100100100 0000010011000100001000000000000000000000 -0000100100101000 0001010001000100001000000000000000000000 -0000100100101100 0000100001000100001000000000000000000000 -0000100100100001 0000010011000100001000000000000000000000 -0000100100101001 0001010010000100001000000000000000000000 -0000100100101101 0000110010000100001000000000000000000000 -0000100100100010 0001010001000100001000000000000000000000 -0000100100100110 0001010010000100001000000000000000000000 -0000100100101110 0001110000000100001000000000000000000000 -0000100100100011 0000100001000100001000000000000000000000 -0000100100100111 0000110010000100001000000000000000000000 -0000100100101011 0001110000000100001000000000000000000000 -0000100111100100 0000010011000100111000000000000000000000 -0000100111101000 0001010001000100111000000000000000000000 -0000100111101100 0000100001000100111000000000000000000000 -0000100111100001 0000010011000100111000000000000000000000 -0000100111101001 0001010010000100111000000000000000000000 -0000100111101101 0000110010000100111000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011100-------- 0000000000000000000000010000000010001000 -11000111-------- 0000000000000000000000000001000000000000 -0000100111100010 0001010001000100111000000000000000000000 -0000100111100110 0001010010000100111000000000000000000000 -0000100111101110 0001110000000100111000000000000000000000 -0000100111100011 0000100001000100111000000000000000000000 -0000100111100111 0000110010000100111000000000000000000000 -0000100111101011 0001110000000100111000000000000000000000 -0000100101010100 0000010011000100010100000000000000000000 -0000100101011000 0001010001000100010100000000000000000000 -0000100101011100 0000100001000100010100000000000000000000 -0000100101010001 0000010011000100010100000000000000000000 -0000100101011001 0001010010000100010100000000000000000000 -0000100101011101 0000110010000100010100000000000000000000 -0000100101010010 0001010001000100010100000000000000000000 -0000100101010110 0001010010000100010100000000000000000000 -0000100101011110 0001110000000100010100000000000000000000 -0000100101010011 0000100001000100010100000000000000000000 -0000100101010111 0000110010000100010100000000000000000000 -0000100101011011 0001110000000100010100000000000000000000 -0000100110010100 0000010011000100100100000000000000000000 -0000100110011000 0001010001000100100100000000000000000000 -0000100110011100 0000100001000100100100000000000000000000 -0000100110010001 0000010011000100100100000000000000000000 -0000100110011001 0001010010000100100100000000000000000000 -0000100110011101 0000110010000100100100000000000000000000 -0000100110010010 0001010001000100100100000000000000000000 -0000100110010110 0001010010000100100100000000000000000000 -0000100110011110 0001110000000100100100000000000000000000 -0000100110010011 0000100001000100100100000000000000000000 -0000100110010111 0000110010000100100100000000000000000000 -0000100110011011 0001110000000100100100000000000000000000 -0000100100010100 0000010011000100000100000000000000000000 -0000100100011000 0001010001000100000100000000000000000000 -0000100100011100 0000100001000100000100000000000000000000 -0000100100010001 0000010011000100000100000000000000000000 -0000100100011001 0001010010000100000100000000000000000000 -0000100100011101 0000110010000100000100000000000000000000 -0000100100010010 0001010001000100000100000000000000000000 -0000100100010110 0001010010000100000100000000000000000000 -0000100100011110 0001110000000100000100000000000000000000 -0000100100010011 0000100001000100000100000000000000000000 -0000100100010111 0000110010000100000100000000000000000000 -0000100100011011 0001110000000100000100000000000000000000 -0000100111010100 0000010011000100110100000000000000000000 -0000100111011000 0001010001000100110100000000000000000000 -0000100111011100 0000100001000100110100000000000000000000 -0000100111010001 0000010011000100110100000000000000000000 -0000100111011001 0001010010000100110100000000000000000000 -0000100111011101 0000110010000100110100000000000000000000 -0000100111010010 0001010001000100110100000000000000000000 -0000100111010110 0001010010000100110100000000000000000000 -0000100111011110 0001110000000100110100000000000000000000 -0000100111010011 0000100001000100110100000000000000000000 -0000100111010111 0000110010000100110100000000000000000000 -0000100111011011 0001110000000100110100000000000000000000 -0000100101000100 0000010011000100010000000000000000000000 -0000100101001000 0001010001000100010000000000000000000000 -0000100101001100 0000100001000100010000000000000000000000 -0000100101000001 0000010011000100010000000000000000000000 -0000100101001001 0001010010000100010000000000000000000000 -0000100101001101 0000110010000100010000000000000000000000 -0000100101000010 0001010001000100010000000000000000000000 -0000100101000110 0001010010000100010000000000000000000000 -0000100101001110 0001110000000100010000000000000000000000 -0000100101000011 0000100001000100010000000000000000000000 -0000100101000111 0000110010000100010000000000000000000000 -0000100101001011 0001110000000100010000000000000000000000 -0000100110000100 0000010011000100100000000000000000000000 -0000100110001000 0001010001000100100000000000000000000000 -0000100110001100 0000100001000100100000000000000000000000 -0000100110000001 0000010011000100100000000000000000000000 -0000100110001001 0001010010000100100000000000000000000000 -0000100110001101 0000110010000100100000000000000000000000 -0000100110000010 0001010001000100100000000000000000000000 -0000100110000110 0001010010000100100000000000000000000000 -0000100110001110 0001110000000100100000000000000000000000 -0000100110000011 0000100001000100100000000000000000000000 -0000100110000111 0000110010000100100000000000000000000000 -0000100110001011 0001110000000100100000000000000000000000 -0000100100000100 0000010011000100000000000000000000000000 -0000100100001000 0001010001000100000000000000000000000000 -0000100100001100 0000100001000100000000000000000000000000 -0000100100000001 0000010011000100000000000000000000000000 -0000100100001001 0001010010000100000000000000000000000000 -0000100100001101 0000110010000100000000000000000000000000 -0000100100000010 0001010001000100000000000000000000000000 -0000100100000110 0001010010000100000000000000000000000000 -0000100100001110 0001110000000100000000000000000000000000 -0000100100000011 0000100001000100000000000000000000000000 -0000100100000111 0000110010000100000000000000000000000000 -0000100100001011 0001110000000100000000000000000000000000 -0000100111000100 0000010011000100110000000000000000000000 -0000100111001000 0001010001000100110000000000000000000000 -0000100111001100 0000100001000100110000000000000000000000 -0000100111000001 0000010011000100110000000000000000000000 -0000100111001001 0001010010000100110000000000000000000000 -0000100111001101 0000110010000100110000000000000000000000 -0000100111000010 0001010001000100110000000000000000000000 -0000100111000110 0001010010000100110000000000000000000000 -0000100111001110 0001110000000100110000000000000000000000 -0000100111000011 0000100001000100110000000000000000000000 -0000100111000111 0000110010000100110000000000000000000000 -0000100111001011 0001110000000100110000000000000000000000 -0000100101110100 0000010011000100011100000000000000000000 -0000100101111000 0001010001000100011100000000000000000000 -0000100101111100 0000100001000100011100000000000000000000 -0000100101110001 0000010011000100011100000000000000000000 -0000100101111001 0001010010000100011100000000000000000000 -0000100101111101 0000110010000100011100000000000000000000 -0000100101110010 0001010001000100011100000000000000000000 -0000100101110110 0001010010000100011100000000000000000000 -0000100101111110 0001110000000100011100000000000000000000 -0000100101110011 0000100001000100011100000000000000000000 -0000100101110111 0000110010000100011100000000000000000000 -0000100101111011 0001110000000100011100000000000000000000 -0000100110110100 0000010011000100101100000000000000000000 -0000100110111000 0001010001000100101100000000000000000000 -0000100110111100 0000100001000100101100000000000000000000 -0000100110110001 0000010011000100101100000000000000000000 -0000100110111001 0001010010000100101100000000000000000000 -0000100110111101 0000110010000100101100000000000000000000 -0000100110110010 0001010001000100101100000000000000000000 -0000100110110110 0001010010000100101100000000000000000000 -0000100110111110 0001110000000100101100000000000000000000 -0000100110110011 0000100001000100101100000000000000000000 -0000100110110111 0000110010000100101100000000000000000000 -0000100110111011 0001110000000100101100000000000000000000 -0000100100110100 0000010011000100001100000000000000000000 -0000100100111000 0001010001000100001100000000000000000000 -0000100100111100 0000100001000100001100000000000000000000 -0000100100110001 0000010011000100001100000000000000000000 -0000100100111001 0001010010000100001100000000000000000000 -0000100100111101 0000110010000100001100000000000000000000 -0000100100110010 0001010001000100001100000000000000000000 -0000100100110110 0001010010000100001100000000000000000000 -0000100100111110 0001110000000100001100000000000000000000 -0000100100110011 0000100001000100001100000000000000000000 -0000100100110111 0000110010000100001100000000000000000000 -0000100100111011 0001110000000100001100000000000000000000 -0000100111110100 0000010011000100111100000000000000000000 -0000100111111000 0001010001000100111100000000000000000000 -0000100111111100 0000100001000100111100000000000000000000 -0000100111110001 0000010011000100111100000000000000000000 -0000100111111001 0001010010000100111100000000000000000000 -0000100111111101 0000110010000100111100000000000000000000 -0000100111110010 0001010001000100111100000000000000000000 -0000100111110110 0001010010000100111100000000000000000000 -0000100111111110 0001110000000100111100000000000000000000 -0000100111110011 0000100001000100111100000000000000000000 -0000100111110111 0000110010000100111100000000000000000000 -0000100111111011 0001110000000100111100000000000000000000 -0000110001100010 0001010000100000011000100000000000000000 -0000110010100010 0001010000100000101000100000000000000000 -0000110001010010 0000100000100000010100100000000000000000 -0000110010010010 0000100000100000100100100000000000000000 -0000110001000010 0001010000100000010000100000000000000000 -0000110010000010 0001010000100000100000100000000000000000 -0000110001110010 0000100000100000011100100000000000000000 -0000110010110010 0000100000100000101100100000000000000000 -0000101101101011 0001010000000000011000100000000000000000 -0000101110101011 0001010000000000101000100000000000000000 -0000101101011011 0000100000000000010100100000000000000000 -0000101110011011 0000100000000000100100100000000000000000 -0000101101001011 0001010000000000010000100000000000000000 -0000101110001011 0001010000000000100000100000000000000000 -0000101101111011 0000100000000000011100100000000000000000 -0000101110111011 0000100000000000101100100000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -01011011-------- 0000000000000000000000000000100010000000 -01011111-------- 0000000000000000000000000000010010000000 -01011100-------- 0000000000000000000000010000000010001000 -01011001-------- 0000000000000000000000000000100000000010 -01011101-------- 0000000000000000000000000000010000000010 -01011010-------- 0000000000000000000000000000100000000001 -01011110-------- 0000000000000000000000000000010000000001 -01001001-------- 0100000010000000000000000000001010001000 -0100100000100001 0100000010000000000000000000101001001000 -0100100000100010 0100000010000000000000000000101000101000 -0100100000100100 0100000010000000000000000000101000011000 -0100100001000001 0100000010000000000000000000011001001000 -0100100001000010 0100000010000000000000000000011000101000 -0100100001000100 0100000010000000000000000000011000011000 -0100100001100001 0100000010000000000000010000000001001000 -0100100001100010 0100000010000000000000010000000000101000 -0100100001100100 0100000010000000000000010000000000011000 -01001000000----- 0100000010000000000000000000000001010000 -01001011-------- 0101000000000000000000000000001010001000 -0100101000100001 0101000000000000000000000000101001001000 -0100101000100010 0101000000000000000000000000101000101000 -0100101000100100 0101000000000000000000000000101000011000 -0100101001000001 0101000000000000000000000000011001001000 -0100101001000010 0101000000000000000000000000011000101000 -0100101001000100 0101000000000000000000000000011000011000 -0100101001100001 0101000000000000000000010000000001001000 -0100101001100010 0101000000000000000000010000000000101000 -0100101001100100 0101000000000000000000010000000000011000 -01001010000----- 0101000000000000000000000000000001100000 -01000001-------- 1000000100000000000000000000001010000100 -0100000000100001 1000000100000000000000000000101001000100 -0100000000100010 1000000100000000000000000000101000100100 -0100000000100100 1000000100000000000000000000101000010100 -0100000001000001 1000000100000000000000000000011001000100 -0100000001000010 1000000100000000000000000000011000100100 -0100000001000100 1000000100000000000000000000011000010100 -0100000001100001 1000000100000000000000010000000001000100 -0100000001100010 1000000100000000000000010000000000100100 -0100000001100100 1000000100000000000000010000000000010100 -01000000000----- 1000000100000000000000000000000100000100 -01000011-------- 1010000000000000000000000000001010000100 -0100001000100001 1010000000000000000000000000101001000100 -0100001000100010 1010000000000000000000000000101000100100 -0100001000100100 1010000000000000000000000000101000010100 -0100001001000001 1010000000000000000000000000011001000100 -0100001001000010 1010000000000000000000000000011000100100 -0100001001000100 1010000000000000000000000000011000010100 -0100001001100001 1010000000000000000000010000000001000100 -0100001001100010 1010000000000000000000010000000000100100 -0100001001100100 1010000000000000000000010000000000010100 -01000010000----- 1010000000000000000000000000000100000100 -0100000010000000 1000000100000000000000001000000000000000 -0100001010000000 1010000000000000000000001000000000000000 -0100110000100001 0000000000000000000000001000101001001000 -0100110000100010 0000000000000000000000001000101000101000 -0100110000100100 0000000000000000000000001000101000011000 -0100110001000001 0000000000000000000000001000011001001000 -0100110001000010 0000000000000000000000001000011000101000 -0100110001000100 0000000000000000000000001000011000011000 -0100110001100001 0000000000000000000000011000000001001000 -0100110001100010 0000000000000000000000011000000000101000 -0100110001100100 0000000000000000000000011000000000011000 -0100100011000000 0100000010000000000000000000000000000000 -0100101011000000 0101000000000000000000000000000000000000 -0100110111000000 0000000000000000000000000000000000000000 -0100011001100001 0000000000000000000000010000000001000100 -0100011001100010 0000000000000000000000010000000000100100 -0100011001100100 0000000000000000000000010000000000010100 -0100011000100001 0000000000000000000000000000101001000100 -0100011000100010 0000000000000000000000000000101000100100 -0100011000100100 0000000000000000000000000000101000010100 -0100011001000001 0000000000000000000000000000011001000100 -0100011001000010 0000000000000000000000000000011000100100 -0100011001000100 0000000000000000000000000000011000010100 -01000110000----- 0000000000000000000000000000000100000100 -0100100010100000 0100000010000000000000000000000000000000 -0100101010100000 0101000000000000000000000000000000000000 -0100011100100001 0000000000000000000000000000101001000100 -0100011100100010 0000000000000000000000000000101000100100 -0100011100100100 0000000000000000000000000000101000010100 -0100011101000001 0000000000000000000000000000011001000100 -0100011101000010 0000000000000000000000000000011000100100 -0100011101000100 0000000000000000000000000000011000010100 -0100000011000000 1000000100000000000000000000000000000000 -0100001011000000 1010000000000000000000000000000000000000 -0100111001100001 0000000000000000000000010000000001001000 -0100111001100010 0000000000000000000000010000000000101000 -0100111001100100 0000000000000000000000010000000000011000 -0100111000100001 0000000000000000000000000000101001001000 -0100111000100010 0000000000000000000000000000101000101000 -0100111000100100 0000000000000000000000000000101000011000 -0100111001000001 0000000000000000000000000000011001001000 -0100111001000010 0000000000000000000000000000011000101000 -0100111001000100 0000000000000000000000000000011000011000 -01001110000----- 0000000000000000000000000000000000100000 -0100000010100000 1000000100000000000000000000000000000000 -0100001010100000 1010000000000000000000000000000000000000 -0100111100100001 0000000000000000000000000000101001001000 -0100111100100010 0000000000000000000000000000101000101000 -0100111100100100 0000000000000000000000000000101000011000 -0100111101000001 0000000000000000000000000000011001001000 -0100111101000010 0000000000000000000000000000011000101000 -0100111101000100 0000000000000000000000000000011000011000 -01011000001----- 0000000000000000000000000000100100001000 -01011000010----- 0000000000000000000000000000010100001000 -01011000100----- 0000000000000000000000000000110100001000 -01010000001----- 0000000000000000000000000000100100000100 -01010000010----- 0000000000000000000000000000010100000100 -01010000100----- 0000000000000000000000000000110100000100 -01011011-------- 0000000000000000000000000000100010000000 -01011111-------- 0000000000000000000000000000010010000000 -01011100-------- 0000000000000000000000010000000010001000 -01010101000----- 0000000000000000000000000000000000000000 -01010110000----- 0000000000000000000000000000000000000000 -01011001-------- 0000000000000000000000000000100000000010 -01011101-------- 0000000000000000000000000000010000000010 -01011010-------- 0000000000000000000000000000100000000001 -01011110-------- 0000000000000000000000000000010000000001 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -1001------------ 0000000000000011000000000000000000000000 -10001000-------- 0100000010000011000000000000101001001000 -10001010-------- 0100000010000011000000000000101000101000 -10001001-------- 0100000010000011000000000000011001001000 -10001011-------- 0100000010000011000000000000011000101000 -10001100-------- 0101000000000011000000000000101001001000 -10001110-------- 0101000000000011000000000000101000101000 -10001101-------- 0101000000000011000000000000011001001000 -10001111-------- 0101000000000011000000000000011000101000 -10000000-------- 1000000100000011000000000000101001000100 -10000010-------- 1000000100000011000000000000101000100100 -10000001-------- 1000000100000011000000000000011001000100 -10000011-------- 1000000100000011000000000000011000100100 -10000100-------- 1010000000000011000000000000101001000100 -10000110-------- 1010000000000011000000000000101000100100 -10000101-------- 1010000000000011000000000000011001000100 -10000111-------- 1010000000000011000000000000011000100100 -1011------------ 0000000000000010000000000000000000000000 -0010000000000000 0000000000000001000000000000000000000000 -1011------------ 0000000000000010000000000000000000000000 -1011------------ 0000000000000010000000000000000000000000 -1011------------ 0000000000000010000000000000000000000000 -1011------------ 0000000000000010000000000000000000000000 -1011------------ 0000000000000010000000000000000000000000 -10101000-------- 0100000010000010000000000000101001001000 -10101010-------- 0100000010000010000000000000101000101000 -10101001-------- 0100000010000010000000000000011001001000 -10101011-------- 0100000010000010000000000000011000101000 -10101100-------- 0101000000000010000000000000101001001000 -10101110-------- 0101000000000010000000000000101000101000 -10101101-------- 0101000000000010000000000000011001001000 -10101111-------- 0101000000000010000000000000011000101000 -10100000-------- 1000000100000010000000000000101001000100 -10100010-------- 1000000100000010000000000000101000100100 -10100001-------- 1000000100000010000000000000011001000100 -10100011-------- 1000000100000010000000000000011000100100 -10100100-------- 1010000000000010000000000000101001000100 -10100110-------- 1010000000000010000000000000101000100100 -10100101-------- 1010000000000010000000000000011001000100 -10100111-------- 1010000000000010000000000000011000100100 -11000001-------- 0000000000000000000000000000000000000000 -11000010-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001001-------- 0000000000000000000000000000000000000000 -11001010-------- 0000000000000000000000000000000000000000 -11001100-------- 0000000000000000000000000000000000000000 -0001------------ ------1--------0------------------------ -0010------------ ------0--------1------------------------ -0011------------ ------1--------1------------------------ -011------------- ------0--------1------------------------ -111------------- ---------------------------------------- -1101------------ ---------------------------------------- -1100111--------- ---------------------------------------- -11001101-------- ---------------------------------------- -11001011-------- ---------------------------------------- -11001000-------- ---------------------------------------- -11000011-------- ---------------------------------------- -11000000-------- ---------------------------------------- -1100010--------- ---------------------------------------- -11000110-------- ---------------------------------------- -0100010--------- ---------------------------------------- -010001111------- ---------------------------------------- -01000111011----- ---------------------------------------- -010001110101---- ---------------------------------------- -0100011101001--- ---------------------------------------- -010001110100011- ---------------------------------------- -0100011101000101 ---------------------------------------- -0100011101000011 ---------------------------------------- -0100011101000000 ---------------------------------------- -01000111000----- ---------------------------------------- -010001110011---- ---------------------------------------- -0100011100101--- ---------------------------------------- -010001110010011- ---------------------------------------- -0100011100100101 ---------------------------------------- -0100011100100011 ---------------------------------------- -0100011100100000 ---------------------------------------- -010001101------- ---------------------------------------- -010001100011---- ---------------------------------------- -0100011000101--- ---------------------------------------- -010001100010011- ---------------------------------------- -0100011000100101 ---------------------------------------- -0100011000100011 ---------------------------------------- -0100011000100000 ---------------------------------------- -010001100101---- ---------------------------------------- -0100011001001--- ---------------------------------------- -010001100100011- ---------------------------------------- -0100011001000101 ---------------------------------------- -0100011001000011 ---------------------------------------- -0100011001000000 ---------------------------------------- -010001100111---- ---------------------------------------- -0100011001101--- ---------------------------------------- -010001100110011- ---------------------------------------- -0100011001100101 ---------------------------------------- -0100011001100011 ---------------------------------------- -0100011001100000 ---------------------------------------- -01000010111----- ---------------------------------------- -010000101101---- ---------------------------------------- -0100001011001--- ---------------------------------------- -01000010110001-- ---------------------------------------- -010000101100001- ---------------------------------------- -0100001011000001 ---------------------------------------- -010000101011---- ---------------------------------------- -0100001010101--- ---------------------------------------- -01000010101001-- ---------------------------------------- -010000101010001- ---------------------------------------- -0100001010100001 ---------------------------------------- -010000101001---- ---------------------------------------- -0100001010001--- ---------------------------------------- -01000010100001-- ---------------------------------------- -010000101000001- ---------------------------------------- -0100001010000001 ---------------------------------------- -010000100111---- ---------------------------------------- -0100001001101--- ---------------------------------------- -010000100110011- ---------------------------------------- -0100001001100101 ---------------------------------------- -0100001001100011 ---------------------------------------- -0100001001100000 ---------------------------------------- -010000100101---- ---------------------------------------- -0100001001001--- ---------------------------------------- -010000100100011- ---------------------------------------- -0100001001000101 ---------------------------------------- -0100001001000011 ---------------------------------------- -0100001001000000 ---------------------------------------- -010000100011---- ---------------------------------------- -0100001000101--- ---------------------------------------- -010000100010011- ---------------------------------------- -0100001000100101 ---------------------------------------- -0100001000100011 ---------------------------------------- -0100001000100000 ---------------------------------------- -01000000111----- ---------------------------------------- -010000001101---- ---------------------------------------- -0100000011001--- ---------------------------------------- -01000000110001-- ---------------------------------------- -010000001100001- ---------------------------------------- -0100000011000001 ---------------------------------------- -010000001011---- ---------------------------------------- -0100000010101--- ---------------------------------------- -01000000101001-- ---------------------------------------- -010000001010001- ---------------------------------------- -0100000010100001 ---------------------------------------- -010000001001---- ---------------------------------------- -0100000010001--- ---------------------------------------- -01000000100001-- ---------------------------------------- -010000001000001- ---------------------------------------- -0100000010000001 ---------------------------------------- -010000000111---- ---------------------------------------- -0100000001101--- ---------------------------------------- -010000000110011- ---------------------------------------- -0100000001100101 ---------------------------------------- -0100000001100011 ---------------------------------------- -0100000001100000 ---------------------------------------- -010000000101---- ---------------------------------------- -0100000001001--- ---------------------------------------- -010000000100011- ---------------------------------------- -0100000001000101 ---------------------------------------- -0100000001000011 ---------------------------------------- -0100000001000000 ---------------------------------------- -010000000011---- ---------------------------------------- -0100000000101--- ---------------------------------------- -010000000010011- ---------------------------------------- -0100000000100101 ---------------------------------------- -0100000000100011 ---------------------------------------- -0100000000100000 ---------------------------------------- -010011111------- ---------------------------------------- -01001111011----- ---------------------------------------- -010011110101---- ---------------------------------------- -0100111101001--- ---------------------------------------- -010011110100011- ---------------------------------------- -0100111101000101 ---------------------------------------- -0100111101000011 ---------------------------------------- -0100111101000000 ---------------------------------------- -01001111000----- ---------------------------------------- -010011110011---- ---------------------------------------- -0100111100101--- ---------------------------------------- -010011110010011- ---------------------------------------- -0100111100100101 ---------------------------------------- -0100111100100011 ---------------------------------------- -0100111100100000 ---------------------------------------- -010011101------- ---------------------------------------- -010011100011---- ---------------------------------------- -0100111000101--- ---------------------------------------- -010011100010011- ---------------------------------------- -0100111000100101 ---------------------------------------- -0100111000100011 ---------------------------------------- -0100111000100000 ---------------------------------------- -010011100101---- ---------------------------------------- -0100111001001--- ---------------------------------------- -010011100100011- ---------------------------------------- -0100111001000101 ---------------------------------------- -0100111001000011 ---------------------------------------- -0100111001000000 ---------------------------------------- -010011100111---- ---------------------------------------- -0100111001101--- ---------------------------------------- -010011100110011- ---------------------------------------- -0100111001100101 ---------------------------------------- -0100111001100011 ---------------------------------------- -0100111001100000 ---------------------------------------- -010011010------- ---------------------------------------- -0100110110------ ---------------------------------------- -01001101111----- ---------------------------------------- -010011011101---- ---------------------------------------- -0100110111001--- ---------------------------------------- -01001101110001-- ---------------------------------------- -010011011100001- ---------------------------------------- -0100110111000001 ---------------------------------------- -010011001------- ---------------------------------------- -010011000111---- ---------------------------------------- -0100110001101--- ---------------------------------------- -010011000110011- ---------------------------------------- -0100110001100101 ---------------------------------------- -0100110001100011 ---------------------------------------- -0100110001100000 ---------------------------------------- -010011000101---- ---------------------------------------- -0100110001001--- ---------------------------------------- -010011000100011- ---------------------------------------- -0100110001000101 ---------------------------------------- -0100110001000011 ---------------------------------------- -0100110001000000 ---------------------------------------- -01001100000----- ---------------------------------------- -010011000011---- ---------------------------------------- -0100110000101--- ---------------------------------------- -010011000010011- ---------------------------------------- -0100110000100101 ---------------------------------------- -0100110000100011 ---------------------------------------- -0100110000100000 ---------------------------------------- -01001010100----- ---------------------------------------- -010010101011---- ---------------------------------------- -0100101010101--- ---------------------------------------- -01001010101001-- ---------------------------------------- -010010101010001- ---------------------------------------- -0100101010100001 ---------------------------------------- -01001010111----- ---------------------------------------- -010010101101---- ---------------------------------------- -0100101011001--- ---------------------------------------- -01001010110001-- ---------------------------------------- -010010101100001- ---------------------------------------- -0100101011000001 ---------------------------------------- -010010100111---- ---------------------------------------- -0100101001101--- ---------------------------------------- -010010100110011- ---------------------------------------- -0100101001100101 ---------------------------------------- -0100101001100011 ---------------------------------------- -0100101001100000 ---------------------------------------- -010010100101---- ---------------------------------------- -0100101001001--- ---------------------------------------- -010010100100011- ---------------------------------------- -0100101001000101 ---------------------------------------- -0100101001000011 ---------------------------------------- -0100101001000000 ---------------------------------------- -010010100011---- ---------------------------------------- -0100101000101--- ---------------------------------------- -010010100010011- ---------------------------------------- -0100101000100101 ---------------------------------------- -0100101000100011 ---------------------------------------- -0100101000100000 ---------------------------------------- -01001000100----- ---------------------------------------- -010010001011---- ---------------------------------------- -0100100010101--- ---------------------------------------- -01001000101001-- ---------------------------------------- -010010001010001- ---------------------------------------- -0100100010100001 ---------------------------------------- -01001000111----- ---------------------------------------- -010010001101---- ---------------------------------------- -0100100011001--- ---------------------------------------- -01001000110001-- ---------------------------------------- -010010001100001- ---------------------------------------- -0100100011000001 ---------------------------------------- -010010000111---- ---------------------------------------- -0100100001101--- ---------------------------------------- -010010000110011- ---------------------------------------- -0100100001100101 ---------------------------------------- -0100100001100011 ---------------------------------------- -0100100001100000 ---------------------------------------- -010010000101---- ---------------------------------------- -0100100001001--- ---------------------------------------- -010010000100011- ---------------------------------------- -0100100001000101 ---------------------------------------- -0100100001000011 ---------------------------------------- -0100100001000000 ---------------------------------------- -010010000011---- ---------------------------------------- -0100100000101--- ---------------------------------------- -010010000010011- ---------------------------------------- -0100100000100101 ---------------------------------------- -0100100000100011 ---------------------------------------- -0100100000100000 ---------------------------------------- -01010111-------- ---------------------------------------- -010101101------- ---------------------------------------- -0101011001------ ---------------------------------------- -01010110001----- ---------------------------------------- -01010100-------- ---------------------------------------- -010101011------- ---------------------------------------- -0101010101------ ---------------------------------------- -01010101001----- ---------------------------------------- -0101001--------- ---------------------------------------- -01010001-------- ---------------------------------------- -0101000011------ ---------------------------------------- -01010000101----- ---------------------------------------- -01010000011----- ---------------------------------------- -01010000000----- ---------------------------------------- -0101100011------ ---------------------------------------- -01011000101----- ---------------------------------------- -01011000011----- ---------------------------------------- -01011000000----- ---------------------------------------- -0000110011------ ---------------------------------------- -0000110010001--- ---------------------------------------- -00001100100001-- ---------------------------------------- -000011001000000- ---------------------------------------- -0000110010000011 ---------------------------------------- -0000110010011--- ---------------------------------------- -00001100100101-- ---------------------------------------- -000011001001000- ---------------------------------------- -0000110010010011 ---------------------------------------- -0000110010111--- ---------------------------------------- -00001100101101-- ---------------------------------------- -000011001011000- ---------------------------------------- -0000110010110011 ---------------------------------------- -0000110010101--- ---------------------------------------- -00001100101001-- ---------------------------------------- -000011001010000- ---------------------------------------- -0000110010100011 ---------------------------------------- -0000110000------ ---------------------------------------- -0000110001001--- ---------------------------------------- -00001100010001-- ---------------------------------------- -000011000100000- ---------------------------------------- -0000110001000011 ---------------------------------------- -0000110001011--- ---------------------------------------- -00001100010101-- ---------------------------------------- -000011000101000- ---------------------------------------- -0000110001010011 ---------------------------------------- -0000110001111--- ---------------------------------------- -00001100011101-- ---------------------------------------- -000011000111000- ---------------------------------------- -0000110001110011 ---------------------------------------- -0000110001101--- ---------------------------------------- -00001100011001-- ---------------------------------------- -000011000110000- ---------------------------------------- -0000110001100011 ---------------------------------------- -000011101100---- ---------------------------------------- -0000111011010--- ---------------------------------------- -00001110110110-- ---------------------------------------- -000011101101110- ---------------------------------------- -0000111011011110 ---------------------------------------- -000011101111---- ---------------------------------------- -0000111011100--- ---------------------------------------- -00001110111011-- ---------------------------------------- -000011101110100- ---------------------------------------- -0000111011101011 ---------------------------------------- -000011101000---- ---------------------------------------- -000011101001010- ---------------------------------------- -0000111010010110 ---------------------------------------- -000011101001000- ---------------------------------------- -0000111010010010 ---------------------------------------- -000011101001100- ---------------------------------------- -0000111010011010 ---------------------------------------- -000011101011---- ---------------------------------------- -000011101010010- ---------------------------------------- -0000111010100111 ---------------------------------------- -000011101010000- ---------------------------------------- -0000111010100011 ---------------------------------------- -000011101010110- ---------------------------------------- -0000111010101111 ---------------------------------------- -000011100000---- ---------------------------------------- -0000111000010--- ---------------------------------------- -00001110000110-- ---------------------------------------- -000011100001110- ---------------------------------------- -0000111000011110 ---------------------------------------- -000011100011---- ---------------------------------------- -0000111000100--- ---------------------------------------- -00001110001011-- ---------------------------------------- -000011100010100- ---------------------------------------- -0000111000101011 ---------------------------------------- -000011100100---- ---------------------------------------- -000011100101010- ---------------------------------------- -0000111001010110 ---------------------------------------- -000011100101000- ---------------------------------------- -0000111001010010 ---------------------------------------- -000011100101100- ---------------------------------------- -0000111001011010 ---------------------------------------- -000011100111---- ---------------------------------------- -000011100110010- ---------------------------------------- -0000111001100111 ---------------------------------------- -000011100110000- ---------------------------------------- -0000111001100011 ---------------------------------------- -000011100110110- ---------------------------------------- -0000111001101111 ---------------------------------------- -00001010-------- ---------------------------------------- -0000101111------ ---------------------------------------- -0000101110000--- ---------------------------------------- -00001011100011-- ---------------------------------------- -000010111000100- ---------------------------------------- -0000101110001010 ---------------------------------------- -0000101110010--- ---------------------------------------- -00001011100111-- ---------------------------------------- -000010111001100- ---------------------------------------- -0000101110011010 ---------------------------------------- -0000101110110--- ---------------------------------------- -00001011101111-- ---------------------------------------- -000010111011100- ---------------------------------------- -0000101110111010 ---------------------------------------- -0000101110100--- ---------------------------------------- -00001011101011-- ---------------------------------------- -000010111010100- ---------------------------------------- -0000101110101010 ---------------------------------------- -0000101100------ ---------------------------------------- -0000101101000--- ---------------------------------------- -00001011010011-- ---------------------------------------- -000010110100100- ---------------------------------------- -0000101101001010 ---------------------------------------- -0000101101010--- ---------------------------------------- -00001011010111-- ---------------------------------------- -000010110101100- ---------------------------------------- -0000101101011010 ---------------------------------------- -0000101101110--- ---------------------------------------- -00001011011111-- ---------------------------------------- -000010110111100- ---------------------------------------- -0000101101111010 ---------------------------------------- -0000101101100--- ---------------------------------------- -00001011011011-- ---------------------------------------- -000010110110100- ---------------------------------------- -0000101101101010 ---------------------------------------- -0000011--------- ---------------------------------------- -0000010111------ ---------------------------------------- -0000010100------ ---------------------------------------- -0000001111------ ---------------------------------------- -00000011101----- ---------------------------------------- -000000111001---- ---------------------------------------- -000000110000---- ---------------------------------------- -000000110011---- ---------------------------------------- -00000011011----- ---------------------------------------- -000000110101---- ---------------------------------------- -00000001-------- ---------------------------------------- -000000001------- ---------------------------------------- -0000000001------ ---------------------------------------- -00000000001----- ---------------------------------------- -000000000001---- ---------------------------------------- -0000000000001--- ---------------------------------------- -00000000000001-- ---------------------------------------- -000000000000001- ---------------------------------------- -0000000000000001 ---------------------------------------- diff --git a/src/benchmarks/espresso/main.c b/src/benchmarks/espresso/main.c deleted file mode 100644 index b82813b..0000000 --- a/src/benchmarks/espresso/main.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Main driver for espresso - * - * Old style -do xxx, -out xxx, etc. are still supported. - */ - -#include "espresso.h" -#include "main.h" /* table definitions for options */ - -static FILE *last_fp; -static int input_type = FD_type; - -#include <stdlib.h> - -void gmalloc_exit(void); - -main(argc, argv) -int argc; -char *argv[]; -{ - int i, j, first, last, strategy, out_type, option; - pPLA PLA, PLA1; - pcover F, Fold, Dold; - pset last1, p; - cost_t cost; - bool error, exact_cover; - long start; - extern char *optarg; - extern int optind; - -#ifdef BWGC - { - extern gc_init(); - gc_init(); - } -#endif - - start = ptime(); - - error = FALSE; - init_runtime(); -#ifdef RANDOM - srandom(314973); -#endif - - option = 0; /* default -D: ESPRESSO */ - out_type = F_type; /* default -o: default is ON-set only */ - debug = 0; /* default -d: no debugging info */ - verbose_debug = FALSE; /* default -v: not verbose */ - print_solution = FALSE; /* default -x: print the solution (!) */ - summary = FALSE; /* default -s: no summary */ - trace = FALSE; /* default -t: no trace information */ - strategy = 0; /* default -S: strategy number */ - first = -1; /* default -R: select range */ - last = -1; - remove_essential = TRUE; /* default -e: */ - force_irredundant = TRUE; - unwrap_onset = TRUE; - single_expand = FALSE; - pos = FALSE; - recompute_onset = FALSE; - use_super_gasp = FALSE; - use_random_order = FALSE; - kiss = FALSE; - echo_comments = TRUE; - echo_unknown_commands = TRUE; - exact_cover = FALSE; /* for -qm option, the default */ - - backward_compatibility_hack(&argc, argv, &option, &out_type); - - - /* parse command line options*/ - while ((i = getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) { - switch(i) { - case 'D': /* -Dcommand invokes a subcommand */ - for(j = 0; option_table[j].name != 0; j++) { - if (strcmp(optarg, option_table[j].name) == 0) { - option = j; - break; - } - } - if (option_table[j].name == 0) { - fprintf(stderr, "%s: bad subcommand \"%s\"\n", - argv[0], optarg); - exit(1); - } - break; - - case 'o': /* -ooutput selects and output option */ - for(j = 0; pla_types[j].key != 0; j++) { - if (strcmp(optarg, pla_types[j].key+1) == 0) { - out_type = pla_types[j].value; - break; - } - } - if (pla_types[j].key == 0) { - fprintf(stderr, "%s: bad output type \"%s\"\n", - argv[0], optarg); - exit(1); - } - break; - - case 'e': /* -eespresso selects an option for espresso */ - for(j = 0; esp_opt_table[j].name != 0; j++) { - if (strcmp(optarg, esp_opt_table[j].name) == 0) { - *(esp_opt_table[j].variable) = esp_opt_table[j].value; - break; - } - } - if (esp_opt_table[j].name == 0) { - fprintf(stderr, "%s: bad espresso option \"%s\"\n", - argv[0], optarg); - exit(1); - } - break; - - case 'd': /* -d turns on (softly) all debug switches */ - debug = debug_table[0].value; - trace = TRUE; - summary = TRUE; - break; - - case 'v': /* -vdebug invokes a debug option */ - verbose_debug = TRUE; - for(j = 0; debug_table[j].name != 0; j++) { - if (strcmp(optarg, debug_table[j].name) == 0) { - debug |= debug_table[j].value; - break; - } - } - if (debug_table[j].name == 0) { - fprintf(stderr, "%s: bad debug type \"%s\"\n", - argv[0], optarg); - exit(1); - } - break; - - case 't': - trace = TRUE; - break; - - case 's': - summary = TRUE; - break; - - case 'x': /* -x suppress printing of results */ - print_solution = FALSE; - break; - - case 'S': /* -S sets a strategy for several cmds */ - strategy = atoi(optarg); - break; - - case 'r': /* -r selects range (outputs or vars) */ - if (sscanf(optarg, "%d-%d", &first, &last) < 2) { - fprintf(stderr, "%s: bad output range \"%s\"\n", - argv[0], optarg); - exit(1); - } - break; - - default: - usage(); - exit(1); - } - } - - /* provide version information and summaries */ - if (summary || trace) { - /* echo command line and arguments */ - printf("#"); - for(i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\n"); - printf("# %s\n", VERSION); - } - - /* the remaining arguments are argv[optind ... argc-1] */ - PLA = PLA1 = NIL(PLA_t); - switch(option_table[option].num_plas) { - case 2: - if (optind+2 < argc) fatal("trailing arguments on command line"); - getPLA(optind++, argc, argv, option, &PLA, out_type); - getPLA(optind++, argc, argv, option, &PLA1, out_type); - break; - case 1: - if (optind+1 < argc) fatal("trailing arguments on command line"); - getPLA(optind++, argc, argv, option, &PLA, out_type); - break; - } - if (optind < argc) fatal("trailing arguments on command line"); - - if (summary || trace) { - if (PLA != NIL(PLA_t)) PLA_summary(PLA); - if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1); - } - -/* - * Now a case-statement to decide what to do - */ - - switch(option_table[option].key) { - - -/******************** Espresso operations ********************/ - - case KEY_ESPRESSO: - Fold = sf_save(PLA->F); - PLA->F = espresso(PLA->F, PLA->D, PLA->R); - EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); - if (error) { - print_solution = FALSE; - PLA->F = Fold; - (void) check_consistency(PLA); - } else { - free_cover(Fold); - } - break; - - case KEY_MANY_ESPRESSO: { - int pla_type; - do { - EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); - if (print_solution) { - fprint_pla(stdout, PLA, out_type); - (void) fflush(stdout); - } - pla_type = PLA->pla_type; - free_PLA(PLA); - setdown_cube(); - FREE(cube.part_size); - } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF); - exit(0); - } - - case KEY_simplify: - EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F); - break; - - case KEY_so: /* minimize all functions as single-output */ - if (strategy < 0 || strategy > 1) { - strategy = 0; - } - so_espresso(PLA, strategy); - break; - - case KEY_so_both: /* minimize all functions as single-output */ - if (strategy < 0 || strategy > 1) { - strategy = 0; - } - so_both_espresso(PLA, strategy); - break; - - case KEY_expand: /* execute expand */ - EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost); - break; - - case KEY_irred: /* extract minimal irredundant subset */ - EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost); - break; - - case KEY_reduce: /* perform reduction */ - EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost); - break; - - case KEY_essen: /* check for essential primes */ - foreach_set(PLA->F, last1, p) { - SET(p, RELESSEN); - RESET(p, NONESSEN); - } - EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost); - free_cover(F); - break; - - case KEY_super_gasp: - PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost); - break; - - case KEY_gasp: - PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost); - break; - - case KEY_make_sparse: /* make_sparse step of Espresso */ - PLA->F = make_sparse(PLA->F, PLA->D, PLA->R); - break; - - case KEY_exact: - exact_cover = TRUE; - - case KEY_qm: - Fold = sf_save(PLA->F); - PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover); - EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); - if (error) { - print_solution = FALSE; - PLA->F = Fold; - (void) check_consistency(PLA); - } - free_cover(Fold); - break; - - case KEY_primes: /* generate all prime implicants */ - EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), - "PRIMES ", PLA->F); - break; - - case KEY_map: /* print out a Karnaugh map of function */ - map(PLA->F); - print_solution = FALSE; - break; - - - -/******************** Output phase and bit pairing ********************/ - - case KEY_opo: /* sasao output phase assignment */ - phase_assignment(PLA, strategy); - break; - - case KEY_opoall: /* try all phase assignments (!) */ - if (first < 0 || first >= cube.part_size[cube.output]) { - first = 0; - } - if (last < 0 || last >= cube.part_size[cube.output]) { - last = cube.part_size[cube.output] - 1; - } - opoall(PLA, first, last, strategy); - break; - - case KEY_pair: /* find an optimal pairing */ - find_optimal_pairing(PLA, strategy); - break; - - case KEY_pairall: /* try all pairings !! */ - pair_all(PLA, strategy); - break; - - - -/******************** Simple cover operations ********************/ - - case KEY_echo: /* echo the PLA */ - break; - - case KEY_taut: /* tautology check */ - printf("ON-set is%sa tautology\n", - tautology(cube1list(PLA->F)) ? " " : " not "); - print_solution = FALSE; - break; - - case KEY_contain: /* single cube containment */ - PLA->F = sf_contain(PLA->F); - break; - - case KEY_intersect: /* cover intersection */ - PLA->F = cv_intersect(PLA->F, PLA1->F); - break; - - case KEY_union: /* cover union */ - PLA->F = sf_union(PLA->F, PLA1->F); - break; - - case KEY_disjoint: /* make cover disjoint */ - PLA->F = make_disjoint(PLA->F); - break; - - case KEY_dsharp: /* cover disjoint-sharp */ - PLA->F = cv_dsharp(PLA->F, PLA1->F); - break; - - case KEY_sharp: /* cover sharp */ - PLA->F = cv_sharp(PLA->F, PLA1->F); - break; - - case KEY_lexsort: /* lexical sort order */ - PLA->F = lex_sort(PLA->F); - break; - - case KEY_stats: /* print info on size */ - if (! summary) PLA_summary(PLA); - print_solution = FALSE; - break; - - case KEY_minterms: /* explode into minterms */ - if (first < 0 || first >= cube.num_vars) { - first = 0; - } - if (last < 0 || last >= cube.num_vars) { - last = cube.num_vars - 1; - } - PLA->F = sf_dupl(unravel_range(PLA->F, first, last)); - break; - - case KEY_d1merge: /* distance-1 merge */ - if (first < 0 || first >= cube.num_vars) { - first = 0; - } - if (last < 0 || last >= cube.num_vars) { - last = cube.num_vars - 1; - } - for(i = first; i <= last; i++) { - PLA->F = d1merge(PLA->F, i); - } - break; - - case KEY_d1merge_in: /* distance-1 merge inputs only */ - for(i = 0; i < cube.num_binary_vars; i++) { - PLA->F = d1merge(PLA->F, i); - } - break; - - case KEY_PLA_verify: /* check two PLAs for equivalence */ - EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost); - if (error) { - printf("PLA comparison failed; the PLA's are not equivalent\n"); - exit(1); - } else { - printf("PLA's compared equal\n"); - exit(0); - } - break; /* silly */ - - case KEY_verify: /* check two covers for equivalence */ - Fold = PLA->F; Dold = PLA->D; F = PLA1->F; - EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost); - if (error) { - printf("PLA comparison failed; the PLA's are not equivalent\n"); - exit(1); - } else { - printf("PLA's compared equal\n"); - exit(0); - } - break; /* silly */ - - case KEY_check: /* check consistency */ - (void) check_consistency(PLA); - print_solution = FALSE; - break; - - case KEY_mapdc: /* compute don't care set */ - map_dcset(PLA); - out_type = FD_type; - break; - - case KEY_equiv: - find_equiv_outputs(PLA); - print_solution = FALSE; - break; - - case KEY_separate: /* remove PLA->D from PLA->F */ - PLA->F = complement(cube2list(PLA->D, PLA->R)); - break; - - case KEY_xor: { - pcover T1 = cv_intersect(PLA->F, PLA1->R); - pcover T2 = cv_intersect(PLA1->F, PLA->R); - free_cover(PLA->F); - PLA->F = sf_contain(sf_join(T1, T2)); - free_cover(T1); - free_cover(T2); - break; - } - - case KEY_fsm: { - disassemble_fsm(PLA, summary); - print_solution = FALSE; - break; - } - - case KEY_test: { - pcover T, E; - T = sf_join(PLA->D, PLA->R); - E = new_cover(10); - sf_free(PLA->F); - EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost); - EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost); - EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost); - sf_free(T); - T = sf_join(PLA->F, PLA->R); - EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost); - EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost); - sf_free(T); - sf_free(E); - break; - } - - - } - - /* Print a runtime summary if trace mode enabled */ - if (trace) { - runtime(); - } - - /* Print total runtime */ - if (summary || trace) { - print_trace(PLA->F, option_table[option].name, ptime()-start); - } - - /* Output the solution */ - if (print_solution) { - EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost); - } - - /* Crash and burn if there was a verify error */ - if (error) { - fatal("cover verification failed"); - } - - /* cleanup all used memory */ - free_PLA(PLA); - FREE(cube.part_size); - setdown_cube(); /* free the cube/cdata structure data */ - sf_cleanup(); /* free unused set structures */ - sm_cleanup(); /* sparse matrix cleanup */ - return 0; -} - - -getPLA(opt, argc, argv, option, PLA, out_type) -int opt; -int argc; -char *argv[]; -int option; -pPLA *PLA; -int out_type; -{ - FILE *fp; - int needs_dcset, needs_offset; - char *fname; - - if (opt >= argc) { - fp = stdin; - fname = "(stdin)"; - } else { - fname = argv[opt]; - if (strcmp(fname, "-") == 0) { - fp = stdin; - } else if ((fp = fopen(argv[opt], "r")) == NULL) { - fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname); - exit(1); - } - } - if (option_table[option].key == KEY_echo) { - needs_dcset = (out_type & D_type) != 0; - needs_offset = (out_type & R_type) != 0; - } else { - needs_dcset = option_table[option].needs_dcset; - needs_offset = option_table[option].needs_offset; - } - - if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) { - fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname); - exit(1); - } - (*PLA)->filename = util_strsav(fname); - filename = (*PLA)->filename; -/* (void) fclose(fp);*/ -/* hackto support -Dmany */ - last_fp = fp; -} - - -runtime() -{ - int i; - long total = 1, temp; - - for(i = 0; i < TIME_COUNT; i++) { - total += total_time[i]; - } - for(i = 0; i < TIME_COUNT; i++) { - if (total_calls[i] != 0) { - temp = 100 * total_time[i]; - printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n", - total_name[i], total_calls[i], print_time(total_time[i]), - temp/total, (10 * (temp%total)) / total); - } - } -} - - -init_runtime() -{ - total_name[READ_TIME] = "READ "; - total_name[WRITE_TIME] = "WRITE "; - total_name[COMPL_TIME] = "COMPL "; - total_name[REDUCE_TIME] = "REDUCE "; - total_name[EXPAND_TIME] = "EXPAND "; - total_name[ESSEN_TIME] = "ESSEN "; - total_name[IRRED_TIME] = "IRRED "; - total_name[GREDUCE_TIME] = "REDUCE_GASP"; - total_name[GEXPAND_TIME] = "EXPAND_GASP"; - total_name[GIRRED_TIME] = "IRRED_GASP "; - total_name[MV_REDUCE_TIME] ="MV_REDUCE "; - total_name[RAISE_IN_TIME] = "RAISE_IN "; - total_name[VERIFY_TIME] = "VERIFY "; - total_name[PRIMES_TIME] = "PRIMES "; - total_name[MINCOV_TIME] = "MINCOV "; -} - - -subcommands() -{ - int i, col; - printf(" "); - col = 16; - for(i = 0; option_table[i].name != 0; i++) { - if ((col + strlen(option_table[i].name) + 1) > 76) { - printf(",\n "); - col = 16; - } else if (i != 0) { - printf(", "); - } - printf("%s", option_table[i].name); - col += strlen(option_table[i].name) + 2; - } - printf("\n"); -} - - -usage() -{ - printf("%s\n\n", VERSION); - printf("SYNOPSIS: espresso [options] [file]\n\n"); - printf(" -d Enable debugging\n"); - printf(" -e[opt] Select espresso option:\n"); - printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n"); - printf(" eat, eatdots, kiss, random\n"); - printf(" -o[type] Select output format:\n"); - printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n"); - printf(" -rn-m Select range for subcommands:\n"); - printf(" d1merge: first and last variables (0 ... m-1)\n"); - printf(" minterms: first and last variables (0 ... m-1)\n"); - printf(" opoall: first and last outputs (0 ... m-1)\n"); - printf(" -s Provide short execution summary\n"); - printf(" -t Provide longer execution trace\n"); - printf(" -x Suppress printing of solution\n"); - printf(" -v[type] Verbose debugging detail (-v '' for all)\n"); - printf(" -D[cmd] Execute subcommand 'cmd':\n"); - subcommands(); - printf(" -Sn Select strategy for subcommands:\n"); - printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n"); - printf(" opoall: 0=minimize, 1=exact\n"); - printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n"); - printf(" pairall: 0=minimize, 1=exact, 2=opo\n"); - printf(" so_espresso: 0=minimize, 1=exact\n"); - printf(" so_both: 0=minimize, 1=exact\n"); -} - -/* - * Hack for backward compatibility (ACK! ) - */ - -backward_compatibility_hack(argc, argv, option, out_type) -int *argc; -char **argv; -int *option; -int *out_type; -{ - int i, j; - - /* Scan the argument list for something to do (default is ESPRESSO) */ - *option = 0; - for(i = 1; i < (*argc)-1; i++) { - if (strcmp(argv[i], "-do") == 0) { - for(j = 0; option_table[j].name != 0; j++) - if (strcmp(argv[i+1], option_table[j].name) == 0) { - *option = j; - delete_arg(argc, argv, i+1); - delete_arg(argc, argv, i); - break; - } - if (option_table[j].name == 0) { - fprintf(stderr, - "espresso: bad keyword \"%s\" following -do\n",argv[i+1]); - exit(1); - } - break; - } - } - - for(i = 1; i < (*argc)-1; i++) { - if (strcmp(argv[i], "-out") == 0) { - for(j = 0; pla_types[j].key != 0; j++) - if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) { - *out_type = pla_types[j].value; - delete_arg(argc, argv, i+1); - delete_arg(argc, argv, i); - break; - } - if (pla_types[j].key == 0) { - fprintf(stderr, - "espresso: bad keyword \"%s\" following -out\n",argv[i+1]); - exit(1); - } - break; - } - } - - for(i = 1; i < (*argc); i++) { - if (argv[i][0] == '-') { - for(j = 0; esp_opt_table[j].name != 0; j++) { - if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) { - delete_arg(argc, argv, i); - *(esp_opt_table[j].variable) = esp_opt_table[j].value; - break; - } - } - } - } - - if (check_arg(argc, argv, "-fdr")) input_type = FDR_type; - if (check_arg(argc, argv, "-fr")) input_type = FR_type; - if (check_arg(argc, argv, "-f")) input_type = F_type; -} - - -/* delete_arg -- delete an argument from the argument list */ -delete_arg(argc, argv, num) -int *argc, num; -register char *argv[]; -{ - register int i; - (*argc)--; - for(i = num; i < *argc; i++) { - argv[i] = argv[i+1]; - } -} - - -/* check_arg -- scan argv for an argument, and return TRUE if found */ -bool check_arg(argc, argv, s) -int *argc; -register char *argv[], *s; -{ - register int i; - for(i = 1; i < *argc; i++) { - if (strcmp(argv[i], s) == 0) { - delete_arg(argc, argv, i); - return TRUE; - } - } - return FALSE; -} diff --git a/src/benchmarks/espresso/main.h b/src/benchmarks/espresso/main.h deleted file mode 100644 index 216ce3a..0000000 --- a/src/benchmarks/espresso/main.h +++ /dev/null @@ -1,113 +0,0 @@ -enum keys { - KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge, - KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand, - KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse, - KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall, - KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp, - KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut, - KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO, - KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm, - KEY_unknown -}; - -/* Lookup table for program options */ -struct { - char *name; - enum keys key; - int num_plas; - bool needs_offset; - bool needs_dcset; -} option_table [] = { - /* ways to minimize functions */ - "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */ - "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE, - "exact", KEY_exact, 1, TRUE, TRUE, - "qm", KEY_qm, 1, TRUE, TRUE, - "single_output", KEY_so, 1, TRUE, TRUE, - "so", KEY_so, 1, TRUE, TRUE, - "so_both", KEY_so_both, 1, TRUE, TRUE, - "simplify", KEY_simplify, 1, FALSE, FALSE, - "echo", KEY_echo, 1, FALSE, FALSE, - - /* output phase assignment and assignment of inputs to two-bit decoders */ - "opo", KEY_opo, 1, TRUE, TRUE, - "opoall", KEY_opoall, 1, TRUE, TRUE, - "pair", KEY_pair, 1, TRUE, TRUE, - "pairall", KEY_pairall, 1, TRUE, TRUE, - - /* Ways to check covers */ - "check", KEY_check, 1, TRUE, TRUE, - "stats", KEY_stats, 1, FALSE, FALSE, - "verify", KEY_verify, 2, FALSE, TRUE, - "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE, - - /* hacks */ - "equiv", KEY_equiv, 1, TRUE, TRUE, - "map", KEY_map, 1, FALSE, FALSE, - "mapdc", KEY_mapdc, 1, FALSE, FALSE, - "fsm", KEY_fsm, 1, FALSE, TRUE, - - /* the basic boolean operations on covers */ - "contain", KEY_contain, 1, FALSE, FALSE, - "d1merge", KEY_d1merge, 1, FALSE, FALSE, - "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE, - "disjoint", KEY_disjoint, 1, TRUE, FALSE, - "dsharp", KEY_dsharp, 2, FALSE, FALSE, - "intersect", KEY_intersect, 2, FALSE, FALSE, - "minterms", KEY_minterms, 1, FALSE, FALSE, - "primes", KEY_primes, 1, FALSE, TRUE, - "separate", KEY_separate, 1, TRUE, TRUE, - "sharp", KEY_sharp, 2, FALSE, FALSE, - "union", KEY_union, 2, FALSE, FALSE, - "xor", KEY_xor, 2, TRUE, TRUE, - - /* debugging only -- call each step of the espresso algorithm */ - "essen", KEY_essen, 1, FALSE, TRUE, - "expand", KEY_expand, 1, TRUE, FALSE, - "gasp", KEY_gasp, 1, TRUE, TRUE, - "irred", KEY_irred, 1, FALSE, TRUE, - "make_sparse", KEY_make_sparse, 1, TRUE, TRUE, - "reduce", KEY_reduce, 1, FALSE, TRUE, - "taut", KEY_taut, 1, FALSE, FALSE, - "super_gasp", KEY_super_gasp, 1, TRUE, TRUE, - "lexsort", KEY_lexsort, 1, FALSE, FALSE, - "test", KEY_test, 1, TRUE, TRUE, - 0, KEY_unknown, 0, FALSE, FALSE /* must be last */ -}; - - -struct { - char *name; - int value; -} debug_table[] = { - "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV, - "compl", COMPL, "essen", ESSEN, - "expand", EXPAND, "expand1", EXPAND1|EXPAND, - "irred", IRRED, "irred1", IRRED1|IRRED, - "reduce", REDUCE, "reduce1", REDUCE1|REDUCE, - "mincov", MINCOV, "mincov1", MINCOV1|MINCOV, - "sparse", SPARSE, "sharp", SHARP, - "taut", TAUT, "gasp", GASP, - "exact", EXACT, - 0, -}; - - -struct { - char *name; - int *variable; - int value; -} esp_opt_table[] = { - "eat", &echo_comments, FALSE, - "eatdots", &echo_unknown_commands, FALSE, - "fast", &single_expand, TRUE, - "kiss", &kiss, TRUE, - "ness", &remove_essential, FALSE, - "nirr", &force_irredundant, FALSE, - "nunwrap", &unwrap_onset, FALSE, - "onset", &recompute_onset, TRUE, - "pos", &pos, TRUE, - "random", &use_random_order, TRUE, - "strong", &use_super_gasp, TRUE, - 0, -}; diff --git a/src/benchmarks/espresso/map.c b/src/benchmarks/espresso/map.c deleted file mode 100644 index d0c041d..0000000 --- a/src/benchmarks/espresso/map.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "espresso.h" - -static pcube Gcube; -static pset Gminterm; - -pset minterms(T) -pcover T; -{ - int size, var; - register pcube last; - - size = 1; - for(var = 0; var < cube.num_vars; var++) - size *= cube.part_size[var]; - Gminterm = set_new(size); - - foreach_set(T, last, Gcube) - explode(cube.num_vars-1, 0); - - return Gminterm; -} - - -void explode(var, z) -int var, z; -{ - int i, last = cube.last_part[var]; - for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++) - if (is_in_set(Gcube, i)) - if (var == 0) - set_insert(Gminterm, z); - else - explode(var-1, z); -} - - -static int mapindex[16][16] = { - 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66, - 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70, - 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78, - 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74, - - 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98, - 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102, - 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110, - 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106, - - - 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226, - 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230, - 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238, - 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234, - - 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194, - 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198, - 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206, - 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202 -}; - -#define POWER2(n) (1 << n) -void map(T) -pcover T; -{ - int j, k, l, other_input_offset, output_offset, outnum, ind; - int largest_input_ind, numout; - char c; - pset m; - bool some_output; - - m = minterms(T); - largest_input_ind = POWER2(cube.num_binary_vars); - numout = cube.part_size[cube.num_vars-1]; - - for(outnum = 0; outnum < numout; outnum++) { - output_offset = outnum * largest_input_ind; - printf("\n\nOutput space # %d\n", outnum); - for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) { - other_input_offset = l * 256; - for(k = 0; k < 16; k++) { - some_output = FALSE; - for(j = 0; j < 16; j++) { - ind = mapindex[k][j] + other_input_offset; - if (ind < largest_input_ind) { - c = is_in_set(m, ind+output_offset) ? '1' : '.'; - putchar(c); - some_output = TRUE; - } - if ((j+1)%4 == 0) - putchar(' '); - if ((j+1)%8 == 0) - printf(" "); - } - if (some_output) - putchar('\n'); - if ((k+1)%4 == 0) { - if (k != 15 && mapindex[k+1][0] >= largest_input_ind) - break; - putchar('\n'); - } - if ((k+1)%8 == 0) - putchar('\n'); - } - } - } - set_free(m); -} diff --git a/src/benchmarks/espresso/matrix.c b/src/benchmarks/espresso/matrix.c deleted file mode 100644 index b012a3e..0000000 --- a/src/benchmarks/espresso/matrix.c +++ /dev/null @@ -1,566 +0,0 @@ -#include "espresso.h" -#include "port.h" -#include "sparse_int.h" - -/* - * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because - * we lose the debugging capability of libmm_t which trashes objects when - * they are free'd. However, FAST_AND_LOOSE is much faster if matrices - * are created and freed frequently. - */ - -#ifdef FAST_AND_LOOSE -sm_element *sm_element_freelist; -sm_row *sm_row_freelist; -sm_col *sm_col_freelist; -#endif - - -sm_matrix * -sm_alloc() -{ - register sm_matrix *A; - - A = ALLOC(sm_matrix, 1); - A->rows = NIL(sm_row *); - A->cols = NIL(sm_col *); - A->nrows = A->ncols = 0; - A->rows_size = A->cols_size = 0; - A->first_row = A->last_row = NIL(sm_row); - A->first_col = A->last_col = NIL(sm_col); - A->user_word = NIL(char); /* for our user ... */ - return A; -} - - -sm_matrix * -sm_alloc_size(row, col) -int row, col; -{ - register sm_matrix *A; - - A = sm_alloc(); - sm_resize(A, row, col); - return A; -} - - -void -sm_free(A) -sm_matrix *A; -{ -#ifdef FAST_AND_LOOSE - register sm_row *prow; - - if (A->first_row != 0) { - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - /* add the elements to the free list of elements */ - prow->last_col->next_col = sm_element_freelist; - sm_element_freelist = prow->first_col; - } - - /* Add the linked list of rows to the row-free-list */ - A->last_row->next_row = sm_row_freelist; - sm_row_freelist = A->first_row; - - /* Add the linked list of cols to the col-free-list */ - A->last_col->next_col = sm_col_freelist; - sm_col_freelist = A->first_col; - } -#else - register sm_row *prow, *pnext_row; - register sm_col *pcol, *pnext_col; - - for(prow = A->first_row; prow != 0; prow = pnext_row) { - pnext_row = prow->next_row; - sm_row_free(prow); - } - for(pcol = A->first_col; pcol != 0; pcol = pnext_col) { - pnext_col = pcol->next_col; - pcol->first_row = pcol->last_row = NIL(sm_element); - sm_col_free(pcol); - } -#endif - - /* Free the arrays to map row/col numbers into pointers */ - FREE(A->rows); - FREE(A->cols); - FREE(A); -} - - -sm_matrix * -sm_dup(A) -sm_matrix *A; -{ - register sm_row *prow; - register sm_element *p; - register sm_matrix *B; - - B = sm_alloc(); - if (A->last_row != 0) { - sm_resize(B, A->last_row->row_num, A->last_col->col_num); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(B, p->row_num, p->col_num); - } - } - } - return B; -} - - -void -sm_resize(A, row, col) -register sm_matrix *A; -int row, col; -{ - register int i, new_size; - - if (row >= A->rows_size) { - new_size = MAX(A->rows_size*2, row+1); - A->rows = REALLOC(sm_row *, A->rows, new_size); - for(i = A->rows_size; i < new_size; i++) { - A->rows[i] = NIL(sm_row); - } - A->rows_size = new_size; - } - - if (col >= A->cols_size) { - new_size = MAX(A->cols_size*2, col+1); - A->cols = REALLOC(sm_col *, A->cols, new_size); - for(i = A->cols_size; i < new_size; i++) { - A->cols[i] = NIL(sm_col); - } - A->cols_size = new_size; - } -} - - -/* - * insert -- insert a value into the matrix - */ -sm_element * -sm_insert(A, row, col) -register sm_matrix *A; -register int row, col; -{ - register sm_row *prow; - register sm_col *pcol; - register sm_element *element; - sm_element *save_element; - - if (row >= A->rows_size || col >= A->cols_size) { - sm_resize(A, row, col); - } - - prow = A->rows[row]; - if (prow == NIL(sm_row)) { - prow = A->rows[row] = sm_row_alloc(); - prow->row_num = row; - sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, - next_row, prev_row, row_num, row, prow); - } - - pcol = A->cols[col]; - if (pcol == NIL(sm_col)) { - pcol = A->cols[col] = sm_col_alloc(); - pcol->col_num = col; - sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, - next_col, prev_col, col_num, col, pcol); - } - - /* get a new item, save its address */ - sm_element_alloc(element); - save_element = element; - - /* insert it into the row list */ - sorted_insert(sm_element, prow->first_col, prow->last_col, - prow->length, next_col, prev_col, col_num, col, element); - - /* if it was used, also insert it into the column list */ - if (element == save_element) { - sorted_insert(sm_element, pcol->first_row, pcol->last_row, - pcol->length, next_row, prev_row, row_num, row, element); - } else { - /* otherwise, it was already in matrix -- free element we allocated */ - sm_element_free(save_element); - } - return element; -} - - -sm_element * -sm_find(A, rownum, colnum) -sm_matrix *A; -int rownum, colnum; -{ - sm_row *prow; - sm_col *pcol; - - prow = sm_get_row(A, rownum); - if (prow == NIL(sm_row)) { - return NIL(sm_element); - } else { - pcol = sm_get_col(A, colnum); - if (pcol == NIL(sm_col)) { - return NIL(sm_element); - } - if (prow->length < pcol->length) { - return sm_row_find(prow, colnum); - } else { - return sm_col_find(pcol, rownum); - } - } -} - - -void -sm_remove(A, rownum, colnum) -sm_matrix *A; -int rownum, colnum; -{ - sm_remove_element(A, sm_find(A, rownum, colnum)); -} - - - -void -sm_remove_element(A, p) -register sm_matrix *A; -register sm_element *p; -{ - register sm_row *prow; - register sm_col *pcol; - - if (p == 0) return; - - /* Unlink the element from its row */ - prow = sm_get_row(A, p->row_num); - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - - /* if no more elements in the row, discard the row header */ - if (prow->first_col == NIL(sm_element)) { - sm_delrow(A, p->row_num); - } - - /* Unlink the element from its column */ - pcol = sm_get_col(A, p->col_num); - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - - /* if no more elements in the column, discard the column header */ - if (pcol->first_row == NIL(sm_element)) { - sm_delcol(A, p->col_num); - } - - sm_element_free(p); -} - -void -sm_delrow(A, i) -sm_matrix *A; -int i; -{ - register sm_element *p, *pnext; - sm_col *pcol; - sm_row *prow; - - prow = sm_get_row(A, i); - if (prow != NIL(sm_row)) { - /* walk across the row */ - for(p = prow->first_col; p != 0; p = pnext) { - pnext = p->next_col; - - /* unlink the item from the column (and delete it) */ - pcol = sm_get_col(A, p->col_num); - sm_col_remove_element(pcol, p); - - /* discard the column if it is now empty */ - if (pcol->first_row == NIL(sm_element)) { - sm_delcol(A, pcol->col_num); - } - } - - /* discard the row -- we already threw away the elements */ - A->rows[i] = NIL(sm_row); - dll_unlink(prow, A->first_row, A->last_row, - next_row, prev_row, A->nrows); - prow->first_col = prow->last_col = NIL(sm_element); - sm_row_free(prow); - } -} - -void -sm_delcol(A, i) -sm_matrix *A; -int i; -{ - register sm_element *p, *pnext; - sm_row *prow; - sm_col *pcol; - - pcol = sm_get_col(A, i); - if (pcol != NIL(sm_col)) { - /* walk down the column */ - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; - - /* unlink the element from the row (and delete it) */ - prow = sm_get_row(A, p->row_num); - sm_row_remove_element(prow, p); - - /* discard the row if it is now empty */ - if (prow->first_col == NIL(sm_element)) { - sm_delrow(A, prow->row_num); - } - } - - /* discard the column -- we already threw away the elements */ - A->cols[i] = NIL(sm_col); - dll_unlink(pcol, A->first_col, A->last_col, - next_col, prev_col, A->ncols); - pcol->first_row = pcol->last_row = NIL(sm_element); - sm_col_free(pcol); - } -} - -void -sm_copy_row(dest, dest_row, prow) -register sm_matrix *dest; -int dest_row; -sm_row *prow; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(dest, dest_row, p->col_num); - } -} - - -void -sm_copy_col(dest, dest_col, pcol) -register sm_matrix *dest; -int dest_col; -sm_col *pcol; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) sm_insert(dest, dest_col, p->row_num); - } -} - - -sm_row * -sm_longest_row(A) -sm_matrix *A; -{ - register sm_row *large_row, *prow; - register int max_length; - - max_length = 0; - large_row = NIL(sm_row); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->length > max_length) { - max_length = prow->length; - large_row = prow; - } - } - return large_row; -} - - -sm_col * -sm_longest_col(A) -sm_matrix *A; -{ - register sm_col *large_col, *pcol; - register int max_length; - - max_length = 0; - large_col = NIL(sm_col); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - if (pcol->length > max_length) { - max_length = pcol->length; - large_col = pcol; - } - } - return large_col; -} - -int -sm_num_elements(A) -sm_matrix *A; -{ - register sm_row *prow; - register int num; - - num = 0; - sm_foreach_row(A, prow) { - num += prow->length; - } - return num; -} - -int -sm_read(fp, A) -FILE *fp; -sm_matrix **A; -{ - int i, j, err; - - *A = sm_alloc(); - while (! feof(fp)) { - err = fscanf(fp, "%d %d", &i, &j); - if (err == EOF) { - return 1; - } else if (err != 2) { - return 0; - } - (void) sm_insert(*A, i, j); - } - return 1; -} - - -int -sm_read_compressed(fp, A) -FILE *fp; -sm_matrix **A; -{ - int i, j, k, nrows, ncols; - unsigned long x; - - *A = sm_alloc(); - if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) { - return 0; - } - sm_resize(*A, nrows, ncols); - - for(i = 0; i < nrows; i++) { - if (fscanf(fp, "%lx", &x) != 1) { - return 0; - } - for(j = 0; j < ncols; j += 32) { - if (fscanf(fp, "%lx", &x) != 1) { - return 0; - } - for(k = j; x != 0; x >>= 1, k++) { - if (x & 1) { - (void) sm_insert(*A, i, k); - } - } - } - } - return 1; -} - - -void -sm_write(fp, A) -FILE *fp; -sm_matrix *A; -{ - register sm_row *prow; - register sm_element *p; - - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num); - } - } -} - -void -sm_print(fp, A) -FILE *fp; -sm_matrix *A; -{ - register sm_row *prow; - register sm_col *pcol; - int c; - - if (A->last_col->col_num >= 100) { - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", (pcol->col_num / 100)%10); - } - putc('\n', fp); - } - - if (A->last_col->col_num >= 10) { - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", (pcol->col_num / 10)%10); - } - putc('\n', fp); - } - - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", pcol->col_num % 10); - } - putc('\n', fp); - - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "-"); - } - putc('\n', fp); - - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - (void) fprintf(fp, "%3d:", prow->row_num); - - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - c = sm_row_find(prow, pcol->col_num) ? '1' : '.'; - putc(c, fp); - } - putc('\n', fp); - } -} - - -void -sm_dump(A, s, max) -sm_matrix *A; -char *s; -int max; -{ - FILE *fp = stdout; - - (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols); - if (A->nrows < max) { - sm_print(fp, A); - } -} - -void -sm_cleanup() -{ -#ifdef FAST_AND_LOOSE - register sm_element *p, *pnext; - register sm_row *prow, *pnextrow; - register sm_col *pcol, *pnextcol; - - for(p = sm_element_freelist; p != 0; p = pnext) { - pnext = p->next_col; - FREE(p); - } - sm_element_freelist = 0; - - for(prow = sm_row_freelist; prow != 0; prow = pnextrow) { - pnextrow = prow->next_row; - FREE(prow); - } - sm_row_freelist = 0; - - for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) { - pnextcol = pcol->next_col; - FREE(pcol); - } - sm_col_freelist = 0; -#endif -} diff --git a/src/benchmarks/espresso/mincov.c b/src/benchmarks/espresso/mincov.c deleted file mode 100644 index e940e5d..0000000 --- a/src/benchmarks/espresso/mincov.c +++ /dev/null @@ -1,370 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - -/* - * mincov.c - */ - -#define USE_GIMPEL -#define USE_INDEP_SET - -static int select_column(); -static void select_essential(); -static int verify_cover(); - -#define fail(why) {\ - (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ - __FILE__, __LINE__, why);\ - (void) fflush(stdout);\ - abort();\ -} - -sm_row * -sm_minimum_cover(A, weight, heuristic, debug_level) -sm_matrix *A; -int *weight; -int heuristic; /* set to 1 for a heuristic covering */ -int debug_level; /* how deep in the recursion to provide info */ -{ - stats_t stats; - solution_t *best, *select; - sm_row *prow, *sol; - sm_col *pcol; - sm_matrix *dup_A; - int nelem, bound; - double sparsity; - - /* Avoid sillyness */ - if (A->nrows <= 0) { - return sm_row_alloc(); /* easy to cover */ - } - - /* Initialize debugging structure */ - stats.start_time = util_cpu_time(); - stats.debug = debug_level > 0; - stats.max_print_depth = debug_level; - stats.max_depth = -1; - stats.nodes = 0; - stats.component = stats.comp_count = 0; - stats.gimpel = stats.gimpel_count = 0; - stats.no_branching = heuristic != 0; - stats.lower_bound = -1; - - /* Check the matrix sparsity */ - nelem = 0; - sm_foreach_row(A, prow) { - nelem += prow->length; - } - sparsity = (double) nelem / (double) (A->nrows * A->ncols); - - /* Determine an upper bound on the solution */ - bound = 1; - sm_foreach_col(A, pcol) { - bound += WEIGHT(weight, pcol->col_num); - } - - /* Perform the covering */ - select = solution_alloc(); - dup_A = sm_dup(A); - best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats); - sm_free(dup_A); - solution_free(select); - - if (stats.debug) { - if (stats.no_branching) { - (void) printf("**** heuristic covering ...\n"); - (void) printf("lower bound = %d\n", stats.lower_bound); - } - (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n", - A->nrows, A->ncols, nelem, sparsity * 100.0); - (void) printf("cover size = %d elements\n", best->row->length); - (void) printf("cover cost = %d\n", best->cost); - (void) printf("time = %s\n", - util_print_time(util_cpu_time() - stats.start_time)); - (void) printf("components = %d\n", stats.comp_count); - (void) printf("gimpel = %d\n", stats.gimpel_count); - (void) printf("nodes = %d\n", stats.nodes); - (void) printf("max_depth = %d\n", stats.max_depth); - } - - sol = sm_row_dup(best->row); - if (! verify_cover(A, sol)) { - fail("mincov: internal error -- cover verification failed\n"); - } - solution_free(best); - return sol; -} - -/* - * Find the best cover for 'A' (given that 'select' already selected); - * - * - abort search if a solution cannot be found which beats 'bound' - * - * - if any solution meets 'lower_bound', then it is the optimum solution - * and can be returned without further work. - */ - -solution_t * -sm_mincov(A, select, weight, lb, bound, depth, stats) -sm_matrix *A; -solution_t *select; -int *weight; -int lb; -int bound; -int depth; -stats_t *stats; -{ - sm_matrix *A1, *A2, *L, *R; - sm_element *p; - solution_t *select1, *select2, *best, *best1, *best2, *indep; - int pick, lb_new, debug; - - /* Start out with some debugging information */ - stats->nodes++; - if (depth > stats->max_depth) stats->max_depth = depth; - debug = stats->debug && (depth <= stats->max_print_depth); - - /* Apply row dominance, column dominance, and select essentials */ - select_essential(A, select, weight, bound); - if (select->cost >= bound) { - return NIL(solution_t); - } - - /* See if gimpel's reduction technique applies ... */ -#ifdef USE_GIMPEL - if ( weight == NIL(int)) { /* hack until we fix it */ - if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) { - return best; - } - } -#endif - -#ifdef USE_INDEP_SET - /* Determine bound from here to final solution using independent-set */ - indep = sm_maximal_independent_set(A, weight); - - /* make sure the lower bound is monotonically increasing */ - lb_new = MAX(select->cost + indep->cost, lb); - pick = select_column(A, weight, indep); - solution_free(indep); -#else - lb_new = select->cost + (A->nrows > 0); - pick = select_column(A, weight, NIL(solution_t)); -#endif - - if (depth == 0) { - stats->lower_bound = lb_new + stats->gimpel; - } - - if (debug) { - (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " "); - (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ", - A->nrows, A->ncols, select->cost + stats->gimpel, - bound + stats->gimpel, lb_new + stats->gimpel, - util_print_time(util_cpu_time()-stats->start_time)); - } - - /* Check for bounding based on no better solution possible */ - if (lb_new >= bound) { - if (debug) (void) printf("bounded\n"); - best = NIL(solution_t); - - - /* Check for new best solution */ - } else if (A->nrows == 0) { - best = solution_dup(select); - if (debug) (void) printf("BEST\n"); - if (stats->debug && stats->component == 0) { - (void) printf("new 'best' solution %d at level %d (time is %s)\n", - best->cost + stats->gimpel, depth, - util_print_time(util_cpu_time() - stats->start_time)); - } - - - /* Check for a partition of the problem */ - } else if (sm_block_partition(A, &L, &R)) { - /* Make L the smaller problem */ - if (L->ncols > R->ncols) { - A1 = L; - L = R; - R = A1; - } - if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows); - stats->comp_count++; - - /* Solve problem for L */ - select1 = solution_alloc(); - stats->component++; - best1 = sm_mincov(L, select1, weight, 0, - bound-select->cost, depth+1, stats); - stats->component--; - solution_free(select1); - sm_free(L); - - /* Add best solution to the selected set */ - if (best1 == NIL(solution_t)) { - best = NIL(solution_t); - } else { - for(p = best1->row->first_col; p != 0; p = p->next_col) { - solution_add(select, weight, p->col_num); - } - solution_free(best1); - - /* recur for the remaining block */ - best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats); - } - sm_free(R); - - /* We've tried as hard as possible, but now we must split and recur */ - } else { - if (debug) (void) printf("pick=%d\n", pick); - - /* Assume we choose this column to be in the covering set */ - A1 = sm_dup(A); - select1 = solution_dup(select); - solution_accept(select1, A1, weight, pick); - best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats); - solution_free(select1); - sm_free(A1); - - /* Update the upper bound if we found a better solution */ - if (best1 != NIL(solution_t) && bound > best1->cost) { - bound = best1->cost; - } - - /* See if this is a heuristic covering (no branching) */ - if (stats->no_branching) { - return best1; - } - - /* Check for reaching lower bound -- if so, don't actually branch */ - if (best1 != NIL(solution_t) && best1->cost == lb_new) { - return best1; - } - - /* Now assume we cannot have that column */ - A2 = sm_dup(A); - select2 = solution_dup(select); - solution_reject(select2, A2, weight, pick); - best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats); - solution_free(select2); - sm_free(A2); - - best = solution_choose_best(best1, best2); - } - - return best; -} - -static int -select_column(A, weight, indep) -sm_matrix *A; -int *weight; -solution_t *indep; -{ - register sm_col *pcol; - register sm_row *prow, *indep_cols; - register sm_element *p, *p1; - double w, best; - int best_col; - - indep_cols = sm_row_alloc(); - if (indep != NIL(solution_t)) { - /* Find which columns are in the independent sets */ - for(p = indep->row->first_col; p != 0; p = p->next_col) { - prow = sm_get_row(A, p->col_num); - for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) { - (void) sm_row_insert(indep_cols, p1->col_num); - } - } - } else { - /* select out of all columns */ - sm_foreach_col(A, pcol) { - (void) sm_row_insert(indep_cols, pcol->col_num); - } - } - - /* Find the best column */ - best_col = -1; - best = -1; - - /* Consider only columns which are in some independent row */ - sm_foreach_row_element(indep_cols, p1) { - pcol = sm_get_col(A, p1->col_num); - - /* Compute the total 'value' of all things covered by the column */ - w = 0.0; - for(p = pcol->first_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - w += 1.0 / ((double) prow->length - 1.0); - } - - /* divide this by the relative cost of choosing this column */ - w = w / (double) WEIGHT(weight, pcol->col_num); - - /* maximize this ratio */ - if (w > best) { - best_col = pcol->col_num; - best = w; - } - } - - sm_row_free(indep_cols); - return best_col; -} - -static void -select_essential(A, select, weight, bound) -sm_matrix *A; -solution_t *select; -int *weight; -int bound; /* must beat this solution */ -{ - register sm_element *p; - register sm_row *prow, *essen; - int delcols, delrows, essen_count; - - do { - /* Check for dominated columns */ - delcols = sm_col_dominance(A, weight); - - /* Find the rows with only 1 element (the essentials) */ - essen = sm_row_alloc(); - sm_foreach_row(A, prow) { - if (prow->length == 1) { - (void) sm_row_insert(essen, prow->first_col->col_num); - } - } - - /* Select all of the elements */ - sm_foreach_row_element(essen, p) { - solution_accept(select, A, weight, p->col_num); - /* Make sure solution still looks good */ - if (select->cost >= bound) { - sm_row_free(essen); - return; - } - } - essen_count = essen->length; - sm_row_free(essen); - - /* Check for dominated rows */ - delrows = sm_row_dominance(A); - - } while (delcols > 0 || delrows > 0 || essen_count > 0); -} - -static int -verify_cover(A, cover) -sm_matrix *A; -sm_row *cover; -{ - sm_row *prow; - - sm_foreach_row(A, prow) { - if (! sm_row_intersects(prow, cover)) { - return 0; - } - } - return 1; -} diff --git a/src/benchmarks/espresso/mincov.h b/src/benchmarks/espresso/mincov.h deleted file mode 100644 index f6a0425..0000000 --- a/src/benchmarks/espresso/mincov.h +++ /dev/null @@ -1,2 +0,0 @@ -/* exported */ -extern sm_row *sm_minimum_cover(); diff --git a/src/benchmarks/espresso/mincov_int.h b/src/benchmarks/espresso/mincov_int.h deleted file mode 100644 index a9f932e..0000000 --- a/src/benchmarks/espresso/mincov_int.h +++ /dev/null @@ -1,44 +0,0 @@ -#include "port.h" -#include "utility.h" -#include "sparse.h" -#include "mincov.h" - - -typedef struct stats_struct stats_t; -struct stats_struct { - int debug; /* 1 if debugging is enabled */ - int max_print_depth; /* dump stats for levels up to this level */ - int max_depth; /* deepest the recursion has gone */ - int nodes; /* total nodes visited */ - int component; /* currently solving a component */ - int comp_count; /* number of components detected */ - int gimpel_count; /* number of times Gimpel reduction applied */ - int gimpel; /* currently inside Gimpel reduction */ - long start_time; /* cpu time when the covering started */ - int no_branching; - int lower_bound; -}; - - - -typedef struct solution_struct solution_t; -struct solution_struct { - sm_row *row; - int cost; -}; - - -extern solution_t *solution_alloc(); -extern void solution_free(); -extern solution_t *solution_dup(); -extern void solution_accept(); -extern void solution_reject(); -extern void solution_add(); -extern solution_t *solution_choose_best(); - -extern solution_t *sm_maximal_independent_set(); -extern solution_t *sm_mincov(); -extern int gimpel_reduce(); - - -#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col]) diff --git a/src/benchmarks/espresso/opo.c b/src/benchmarks/espresso/opo.c deleted file mode 100644 index 1951cb9..0000000 --- a/src/benchmarks/espresso/opo.c +++ /dev/null @@ -1,615 +0,0 @@ -#include "espresso.h" - -/* - * Phase assignment technique (T. Sasao): - * - * 1. create a function with 2*m outputs which implements the - * original function and its complement for each output - * - * 2. minimize this function - * - * 3. choose the minimum number of prime implicants from the - * result of step 2 which are needed to realize either a function - * or its complement for each output - * - * Step 3 is performed in a rather crude way -- by simply multiplying - * out a large expression of the form: - * - * I = (ab + cdef)(acd + bgh) ... - * - * which is a product of m expressions where each expression has two - * product terms -- one representing which primes are needed for the - * function, and one representing which primes are needed for the - * complement. The largest product term resulting shows which primes - * to keep to implement one function or the other for each output. - * For problems with many outputs, this may grind to a - * halt. - * - * Untried: form complement of I and use unate_complement ... - * - * I have unsuccessfully tried several modifications to the basic - * algorithm. The first is quite simple: use Sasao's technique, but - * only commit to a single output at a time (rather than all - * outputs). The goal would be that the later minimizations can "take - * into account" the partial assignment at each step. This is - * expensive (m+1 minimizations rather than 2), and the results are - * discouraging. - * - * The second modification is rather complicated. The result from the - * minimization in step 2 is guaranteed to be minimal. Hence, for - * each output, the set of primes with a 1 in that output are both - * necessary and sufficient to implement the function. Espresso - * achieves the minimality using the routine MAKE_SPARSE. The - * modification is to prevent MAKE_SPARSE from running. Hence, there - * are potentially many subsets of the set of primes with a 1 in a - * column which can be used to implement that output. We use - * IRREDUNDANT to enumerate all possible subsets and then proceed as - * before. - */ - -static int opo_no_make_sparse; -static int opo_repeated; -static int opo_exact; -static void minimize(); - -void phase_assignment(PLA, opo_strategy) -pPLA PLA; -int opo_strategy; -{ - opo_no_make_sparse = opo_strategy % 2; - skip_make_sparse = opo_no_make_sparse; - opo_repeated = (opo_strategy / 2) % 2; - opo_exact = (opo_strategy / 4) % 2; - - /* Determine a phase assignment */ - if (PLA->phase != NULL) { - FREE(PLA->phase); - } - - if (opo_repeated) { - PLA->phase = set_save(cube.fullset); - repeated_phase_assignment(PLA); - } else { - PLA->phase = find_phase(PLA, 0, (pcube) NULL); - } - - /* Now minimize with this assignment */ - skip_make_sparse = FALSE; - (void) set_phase(PLA); - minimize(PLA); -} - -/* - * repeated_phase_assignment -- an alternate strategy which commits - * to a single phase assignment a step at a time. Performs m + 1 - * minimizations ! - */ -void repeated_phase_assignment(PLA) -pPLA PLA; -{ - int i; - pcube phase; - - for(i = 0; i < cube.part_size[cube.output]; i++) { - - /* Find best assignment for all undecided outputs */ - phase = find_phase(PLA, i, PLA->phase); - - /* Commit for only a single output ... */ - if (! is_in_set(phase, cube.first_part[cube.output] + i)) { - set_remove(PLA->phase, cube.first_part[cube.output] + i); - } - - if (trace || summary) { - printf("\nOPO loop for output #%d\n", i); - printf("PLA->phase is %s\n", pc1(PLA->phase)); - printf("phase is %s\n", pc1(phase)); - } - set_free(phase); - } -} - - -/* - * find_phase -- find a phase assignment for the PLA for all outputs starting - * with output number first_output. - */ -pcube find_phase(PLA, first_output, phase1) -pPLA PLA; -int first_output; -pcube phase1; -{ - pcube phase; - pPLA PLA1; - - phase = set_save(cube.fullset); - - /* setup the double-phase characteristic function, resize the cube */ - PLA1 = new_PLA(); - PLA1->F = sf_save(PLA->F); - PLA1->R = sf_save(PLA->R); - PLA1->D = sf_save(PLA->D); - if (phase1 != NULL) { - PLA1->phase = set_save(phase1); - (void) set_phase(PLA1); - } - EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F); - - /* minimize the double-phase function */ - minimize(PLA1); - - /* set the proper phases according to what gives a minimum solution */ - EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output), - "OPO ", PLA1->F); - free_PLA(PLA1); - - /* set the cube structure to reflect the old size */ - setdown_cube(); - cube.part_size[cube.output] -= - (cube.part_size[cube.output] - first_output) / 2; - cube_setup(); - - return phase; -} - -/* - * opo -- multiply the expression out to determine a minimum subset of - * primes. - */ - -/*ARGSUSED*/ -pcover opo(phase, T, D, R, first_output) -pcube phase; -pcover T, D, R; -int first_output; -{ - int offset, output, i, last_output, ind; - pset pdest, select, p, p1, last, last1, not_covered, tmp; - pset_family temp, T1, T2; - - /* must select all primes for outputs [0 .. first_output-1] */ - select = set_full(T->count); - for(output = 0; output < first_output; output++) { - ind = cube.first_part[cube.output] + output; - foreachi_set(T, i, p) { - if (is_in_set(p, ind)) { - set_remove(select, i); - } - } - } - - /* Recursively perform the intersections */ - offset = (cube.part_size[cube.output] - first_output) / 2; - last_output = first_output + offset - 1; - temp = opo_recur(T, D, select, offset, first_output, last_output); - - /* largest set is on top -- select primes which are inferred from it */ - pdest = temp->data; - T1 = new_cover(T->count); - foreachi_set(T, i, p) { - if (! is_in_set(pdest, i)) { - T1 = sf_addset(T1, p); - } - } - - set_free(select); - sf_free(temp); - - /* finding phases is difficult -- see which functions are not covered */ - T2 = complement(cube1list(T1)); - not_covered = new_cube(); - tmp = new_cube(); - foreach_set(T, last, p) { - foreach_set(T2, last1, p1) { - if (cdist0(p, p1)) { - (void) set_or(not_covered, not_covered, set_and(tmp, p, p1)); - } - } - } - free_cover(T); - free_cover(T2); - set_free(tmp); - - /* Now reflect the phase choice in a single cube */ - for(output = first_output; output <= last_output; output++) { - ind = cube.first_part[cube.output] + output; - if (is_in_set(not_covered, ind)) { - if (is_in_set(not_covered, ind + offset)) { - fatal("error in output phase assignment"); - } else { - set_remove(phase, ind); - } - } - } - set_free(not_covered); - return T1; -} - -pset_family opo_recur(T, D, select, offset, first, last) -pcover T, D; -pcube select; -int offset, first, last; -{ - static int level = 0; - int middle; - pset_family sl, sr, temp; - - level++; - if (first == last) { -#if 0 - if (opo_no_make_sparse) { - temp = form_cover_table(T, D, select, first, first + offset); - } else { - temp = opo_leaf(T, select, first, first + offset); - } -#else - temp = opo_leaf(T, select, first, first + offset); -#endif - } else { - middle = (first + last) / 2; - sl = opo_recur(T, D, select, offset, first, middle); - sr = opo_recur(T, D, select, offset, middle+1, last); - temp = unate_intersect(sl, sr, level == 1); - if (trace) { - printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1, - temp->count, sl->count, sr->count, print_time(ptime())); - (void) fflush(stdout); - } - free_cover(sl); - free_cover(sr); - } - level--; - return temp; -} - - -pset_family opo_leaf(T, select, out1, out2) -register pcover T; -pset select; -int out1, out2; -{ - register pset_family temp; - register pset p, pdest; - register int i; - - out1 += cube.first_part[cube.output]; - out2 += cube.first_part[cube.output]; - - /* Allocate space for the result */ - temp = sf_new(2, T->count); - - /* Find which primes are needed for the ON-set of this fct */ - pdest = GETSET(temp, temp->count++); - (void) set_copy(pdest, select); - foreachi_set(T, i, p) { - if (is_in_set(p, out1)) { - set_remove(pdest, i); - } - } - - /* Find which primes are needed for the OFF-set of this fct */ - pdest = GETSET(temp, temp->count++); - (void) set_copy(pdest, select); - foreachi_set(T, i, p) { - if (is_in_set(p, out2)) { - set_remove(pdest, i); - } - } - - return temp; -} - -#if 0 -pset_family form_cover_table(F, D, select, f, fbar) -pcover F, D; -pset select; -int f, fbar; /* indices of f and fbar in the output part */ -{ - register int i; - register pcube p; - pset_family f_table, fbar_table; - - /* setup required for fcube_is_covered */ - Rp_size = F->count; - Rp_start = set_new(Rp_size); - foreachi_set(F, i, p) { - PUTSIZE(p, i); - } - foreachi_set(D, i, p) { - RESET(p, REDUND); - } - - f_table = find_covers(F, D, select, f); - fbar_table = find_covers(F, D, select, fbar); - f_table = sf_append(f_table, fbar_table); - - set_free(Rp_start); - return f_table; -} - - -pset_family find_covers(F, D, select, n) -pcover F, D; -register pset select; -int n; -{ - register pset p, last, new; - pcover F1; - pcube *Flist; - pset_family f_table, table; - int i; - - n += cube.first_part[cube.output]; - - /* save cubes in this output, and remove the output variable */ - F1 = new_cover(F->count); - foreach_set(F, last, p) - if (is_in_set(p, n)) { - new = GETSET(F1, F1->count++); - set_or(new, p, cube.var_mask[cube.output]); - PUTSIZE(new, SIZE(p)); - SET(new, REDUND); - } - - /* Find ways (sop form) to fail to cover output indexed by n */ - Flist = cube2list(F1, D); - table = sf_new(10, Rp_size); - foreach_set(F1, last, p) { - set_fill(Rp_start, Rp_size); - set_remove(Rp_start, SIZE(p)); - table = sf_append(table, fcube_is_covered(Flist, p)); - RESET(p, REDUND); - } - set_fill(Rp_start, Rp_size); - foreach_set(table, last, p) { - set_diff(p, Rp_start, p); - } - - /* complement this to get possible ways to cover the function */ - for(i = 0; i < Rp_size; i++) { - if (! is_in_set(select, i)) { - p = set_new(Rp_size); - set_insert(p, i); - table = sf_addset(table, p); - set_free(p); - } - } - f_table = unate_compl(table); - - /* what a pain, but we need bitwise complement of this */ - set_fill(Rp_start, Rp_size); - foreach_set(f_table, last, p) { - set_diff(p, Rp_start, p); - } - - free_cubelist(Flist); - sf_free(F1); - return f_table; -} -#endif - -/* - * Take a PLA (ON-set, OFF-set and DC-set) and create the - * "double-phase characteristic function" which is merely a new - * function which has twice as many outputs and realizes both the - * function and the complement. - * - * The cube structure is assumed to represent the PLA upon entering. - * It will be modified to represent the double-phase function upon - * exit. - * - * Only the outputs numbered starting with "first_output" are - * duplicated in the output part - */ - -output_phase_setup(PLA, first_output) -INOUT pPLA PLA; -int first_output; -{ - pcover F, R, D; - pcube mask, mask1, last; - int first_part, offset; - bool save; - register pcube p, pr, pf; - register int i, last_part; - - if (cube.output == -1) - fatal("output_phase_setup: must have an output"); - - F = PLA->F; - D = PLA->D; - R = PLA->R; - first_part = cube.first_part[cube.output] + first_output; - last_part = cube.last_part[cube.output]; - offset = cube.part_size[cube.output] - first_output; - - /* Change the output size, setup the cube structure */ - setdown_cube(); - cube.part_size[cube.output] += offset; - cube_setup(); - - /* Create a mask to select that part of the cube which isn't changing */ - mask = set_save(cube.fullset); - for(i = first_part; i < cube.size; i++) - set_remove(mask, i); - mask1 = set_save(mask); - for(i = cube.first_part[cube.output]; i < first_part; i++) { - set_remove(mask1, i); - } - - PLA->F = new_cover(F->count + R->count); - PLA->R = new_cover(F->count + R->count); - PLA->D = new_cover(D->count); - - foreach_set(F, last, p) { - pf = GETSET(PLA->F, (PLA->F)->count++); - pr = GETSET(PLA->R, (PLA->R)->count++); - INLINEset_and(pf, mask, p); - INLINEset_and(pr, mask1, p); - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - set_insert(pf, i); - save = FALSE; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - save = TRUE, set_insert(pr, i+offset); - if (! save) PLA->R->count--; - } - - foreach_set(R, last, p) { - pf = GETSET(PLA->F, (PLA->F)->count++); - pr = GETSET(PLA->R, (PLA->R)->count++); - INLINEset_and(pf, mask1, p); - INLINEset_and(pr, mask, p); - save = FALSE; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - save = TRUE, set_insert(pf, i+offset); - if (! save) PLA->F->count--; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - set_insert(pr, i); - } - - foreach_set(D, last, p) { - pf = GETSET(PLA->D, (PLA->D)->count++); - INLINEset_and(pf, mask, p); - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) { - set_insert(pf, i); - set_insert(pf, i+offset); - } - } - - free_cover(F); - free_cover(D); - free_cover(R); - set_free(mask); - set_free(mask1); -} - -/* - * set_phase -- given a "cube" which describes which phases of the output - * are to be implemented, compute the appropriate on-set and off-set - */ -pPLA set_phase(PLA) -INOUT pPLA PLA; -{ - pcover F1, R1; - register pcube last, p, outmask; - register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1]; - - outmask = cube.var_mask[cube.num_vars - 1]; - set_diff(phase1, outmask, phase); - set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1); - F1 = new_cover((PLA->F)->count + (PLA->R)->count); - R1 = new_cover((PLA->F)->count + (PLA->R)->count); - - foreach_set(PLA->F, last, p) { - if (! setp_disjoint(set_and(temp, p, phase), outmask)) - set_copy(GETSET(F1, F1->count++), temp); - if (! setp_disjoint(set_and(temp, p, phase1), outmask)) - set_copy(GETSET(R1, R1->count++), temp); - } - foreach_set(PLA->R, last, p) { - if (! setp_disjoint(set_and(temp, p, phase), outmask)) - set_copy(GETSET(R1, R1->count++), temp); - if (! setp_disjoint(set_and(temp, p, phase1), outmask)) - set_copy(GETSET(F1, F1->count++), temp); - } - free_cover(PLA->F); - free_cover(PLA->R); - PLA->F = F1; - PLA->R = R1; - return PLA; -} - -#define POW2(x) (1 << (x)) - -void opoall(PLA, first_output, last_output, opo_strategy) -pPLA PLA; -int first_output, last_output; -int opo_strategy; -{ - pcover F, D, R, best_F, best_D, best_R; - int i, j, ind, num; - pcube bestphase; - - opo_exact = opo_strategy; - - if (PLA->phase != NULL) { - set_free(PLA->phase); - } - - bestphase = set_save(cube.fullset); - best_F = sf_save(PLA->F); - best_D = sf_save(PLA->D); - best_R = sf_save(PLA->R); - - for(i = 0; i < POW2(last_output - first_output + 1); i++) { - - /* save the initial PLA covers */ - F = sf_save(PLA->F); - D = sf_save(PLA->D); - R = sf_save(PLA->R); - - /* compute the phase cube for this iteration */ - PLA->phase = set_save(cube.fullset); - num = i; - for(j = last_output; j >= first_output; j--) { - if (num % 2 == 0) { - ind = cube.first_part[cube.output] + j; - set_remove(PLA->phase, ind); - } - num /= 2; - } - - /* set the phase and minimize */ - (void) set_phase(PLA); - printf("# phase is %s\n", pc1(PLA->phase)); - summary = TRUE; - minimize(PLA); - - /* see if this is the best so far */ - if (PLA->F->count < best_F->count) { - /* save new best solution */ - set_copy(bestphase, PLA->phase); - sf_free(best_F); - sf_free(best_D); - sf_free(best_R); - best_F = PLA->F; - best_D = PLA->D; - best_R = PLA->R; - } else { - /* throw away the solution */ - free_cover(PLA->F); - free_cover(PLA->D); - free_cover(PLA->R); - } - set_free(PLA->phase); - - /* restore the initial PLA covers */ - PLA->F = F; - PLA->D = D; - PLA->R = R; - } - - /* one more minimization to restore the best answer */ - PLA->phase = bestphase; - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = best_F; - PLA->D = best_D; - PLA->R = best_R; -} - -static void minimize(PLA) -pPLA PLA; -{ - if (opo_exact) { - EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F); - } else { - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F); - } -} diff --git a/src/benchmarks/espresso/pair.c b/src/benchmarks/espresso/pair.c deleted file mode 100644 index 50e86aa..0000000 --- a/src/benchmarks/espresso/pair.c +++ /dev/null @@ -1,666 +0,0 @@ -#include "espresso.h" - -void set_pair(PLA) -pPLA PLA; -{ - set_pair1(PLA, TRUE); -} - -void set_pair1(PLA, adjust_labels) -pPLA PLA; -bool adjust_labels; -{ - int i, var, *paired, newvar; - int old_num_vars, old_num_binary_vars, old_size, old_mv_start; - int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start; - ppair pair = PLA->pair; - char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar; - - if (adjust_labels) - makeup_labels(PLA); - - /* Check the pair structure for valid entries and see which binary - variables are left unpaired - */ - paired = ALLOC(bool, cube.num_binary_vars); - for(var = 0; var < cube.num_binary_vars; var++) - paired[var] = FALSE; - for(i = 0; i < pair->cnt; i++) - if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) && - (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) { - paired[pair->var1[i]-1] = TRUE; - paired[pair->var2[i]-1] = TRUE; - } else - fatal("can only pair binary-valued variables"); - - PLA->F = delvar(pairvar(PLA->F, pair), paired); - PLA->R = delvar(pairvar(PLA->R, pair), paired); - PLA->D = delvar(pairvar(PLA->D, pair), paired); - - /* Now painfully adjust the cube size */ - old_size = cube.size; - old_num_vars = cube.num_vars; - old_num_binary_vars = cube.num_binary_vars; - old_mv_start = cube.first_part[cube.num_binary_vars]; - /* Create the new cube.part_size vector and setup the cube structure */ - new_num_binary_vars = 0; - for(var = 0; var < old_num_binary_vars; var++) - new_num_binary_vars += (paired[var] == FALSE); - new_num_vars = new_num_binary_vars + pair->cnt; - new_num_vars += old_num_vars - old_num_binary_vars; - new_part_size = ALLOC(int, new_num_vars); - for(var = 0; var < pair->cnt; var++) - new_part_size[new_num_binary_vars + var] = 4; - for(var = 0; var < old_num_vars - old_num_binary_vars; var++) - new_part_size[new_num_binary_vars + pair->cnt + var] = - cube.part_size[old_num_binary_vars + var]; - setdown_cube(); - FREE(cube.part_size); - cube.num_vars = new_num_vars; - cube.num_binary_vars = new_num_binary_vars; - cube.part_size = new_part_size; - cube_setup(); - - /* hack with the labels to get them correct */ - if (adjust_labels) { - oldlabel = PLA->label; - PLA->label = ALLOC(char *, cube.size); - for(var = 0; var < pair->cnt; var++) { - newvar = cube.num_binary_vars*2 + var*4; - var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1]; - var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1]; - var1bar = oldlabel[ (pair->var1[var]-1) * 2]; - var2bar = oldlabel[ (pair->var2[var]-1) * 2]; - (void) sprintf(scratch, "%s+%s", var1bar, var2bar); - PLA->label[newvar] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1bar, var2); - PLA->label[newvar+1] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1, var2bar); - PLA->label[newvar+2] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1, var2); - PLA->label[newvar+3] = util_strsav(scratch); - } - /* Copy the old labels for the unpaired binary vars */ - i = 0; - for(var = 0; var < old_num_binary_vars; var++) { - if (paired[var] == FALSE) { - PLA->label[2*i] = oldlabel[2*var]; - PLA->label[2*i+1] = oldlabel[2*var+1]; - oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL; - i++; - } - } - /* Copy the old labels for the remaining unpaired vars */ - new_mv_start = cube.num_binary_vars*2 + pair->cnt*4; - for(i = old_mv_start; i < old_size; i++) { - PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i]; - oldlabel[i] = (char *) NULL; - } - /* free remaining entries in oldlabel */ - for(i = 0; i < old_size; i++) - if (oldlabel[i] != (char *) NULL) - FREE(oldlabel[i]); - FREE(oldlabel); - } - - /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/ - for(var = 0; var < pair->cnt; var++) - cube.sparse[cube.num_binary_vars + var] = 0; - FREE(paired); -} - -pcover pairvar(A, pair) -pcover A; -ppair pair; -{ - register pcube last, p; - register int val, p1, p2, b1, b0; - int insert_col, pairnum; - - insert_col = cube.first_part[cube.num_vars - 1]; - - /* stretch the cover matrix to make room for the paired variables */ - A = sf_delcol(A, insert_col, -4*pair->cnt); - - /* compute the paired values */ - foreach_set(A, last, p) { - for(pairnum = 0; pairnum < pair->cnt; pairnum++) { - p1 = cube.first_part[pair->var1[pairnum] - 1]; - p2 = cube.first_part[pair->var2[pairnum] - 1]; - b1 = is_in_set(p, p2+1); - b0 = is_in_set(p, p2); - val = insert_col + pairnum * 4; - if (/* a0 */ is_in_set(p, p1)) { - if (b0) - set_insert(p, val + 3); - if (b1) - set_insert(p, val + 2); - } - if (/* a1 */ is_in_set(p, p1+1)) { - if (b0) - set_insert(p, val + 1); - if (b1) - set_insert(p, val); - } - } - } - return A; -} - - -/* delvar -- delete variables from A, minimize the number of column shifts */ -pcover delvar(A, paired) -pcover A; -bool paired[]; -{ - bool run; - int first_run, run_length, var, offset = 0; - - run = FALSE; run_length = 0; - for(var = 0; var < cube.num_binary_vars; var++) - if (paired[var]) - if (run) - run_length += cube.part_size[var]; - else { - run = TRUE; - first_run = cube.first_part[var]; - run_length = cube.part_size[var]; - } - else - if (run) { - A = sf_delcol(A, first_run-offset, run_length); - run = FALSE; - offset += run_length; - } - if (run) - A = sf_delcol(A, first_run-offset, run_length); - return A; -} - -/* - find_optimal_pairing -- find which binary variables should be paired - to maximally reduce the number of terms - - This is essentially the technique outlined by T. Sasao in the - Trans. on Comp., Oct 1984. We estimate the cost of pairing each - pair individually using 1 of 4 strategies: (1) algebraic division - of F by the pair (exactly T. Sasao technique); (2) strong division - of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from - espresso); (3) full minimization using espresso; (4) exact - minimization. These are in order of both increasing accuracy and - increasing difficulty (!) - - Once the n squared pairs have been evaluated, T. Sasao proposes a - graph covering of nodes by disjoint edges. For now, I solve this - problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n - variables when n is even). Note that solving this problem exactly - is the same as evaluating the cost function for all possible - pairings. - - n pairs - - 1, 2 1 - 3, 4 3 - 5, 6 15 - 7, 8 105 - 9,10 945 - 11,12 10,395 - 13,14 135,135 - 15,16 2,027,025 - 17,18 34,459,425 - 19,20 654,729,075 -*/ -void find_optimal_pairing(PLA, strategy) -pPLA PLA; -int strategy; -{ - int i, j, **cost_array; - - cost_array = find_pairing_cost(PLA, strategy); - - if (summary) { - printf(" "); - for(i = 0; i < cube.num_binary_vars; i++) - printf("%3d ", i+1); - printf("\n"); - for(i = 0; i < cube.num_binary_vars; i++) { - printf("%3d ", i+1); - for(j = 0; j < cube.num_binary_vars; j++) - printf("%3d ", cost_array[i][j]); - printf("\n"); - } - } - - if (cube.num_binary_vars <= 14) { - PLA->pair = pair_best_cost(cost_array); - } else { - (void) greedy_best_cost(cost_array, &(PLA->pair)); - } - printf("# "); - print_pair(PLA->pair); - - for(i = 0; i < cube.num_binary_vars; i++) - FREE(cost_array[i]); - FREE(cost_array); - - set_pair(PLA); - EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); -} - -int **find_pairing_cost(PLA, strategy) -pPLA PLA; -int strategy; -{ - int var1, var2, **cost_array; - int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost; - pcover T, Fsave, Dsave, Rsave; - pset mask; -/* char *s;*/ - - /* data is returned in the cost array */ - cost_array = ALLOC(int *, cube.num_binary_vars); - for(i = 0; i < cube.num_binary_vars; i++) - cost_array[i] = ALLOC(int, cube.num_binary_vars); - for(i = 0; i < cube.num_binary_vars; i++) - for(j = 0; j < cube.num_binary_vars; j++) - cost_array[i][j] = 0; - - /* Setup the pair structure for pairing variables together */ - PLA->pair = pair_new(1); - PLA->pair->cnt = 1; - - for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) { - for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) { - /* if anything but simple strategy, perform setup */ - if (strategy > 0) { - /* save the original covers */ - Fsave = sf_save(PLA->F); - Dsave = sf_save(PLA->D); - Rsave = sf_save(PLA->R); - - /* save the original cube structure */ - xnum_binary_vars = cube.num_binary_vars; - xnum_vars = cube.num_vars; - xpart_size = ALLOC(int, cube.num_vars); - for(i = 0; i < cube.num_vars; i++) - xpart_size[i] = cube.part_size[i]; - - /* pair two variables together */ - PLA->pair->var1[0] = var1 + 1; - PLA->pair->var2[0] = var2 + 1; - set_pair1(PLA, /* adjust_labels */ FALSE); - } - - - /* decide how to best estimate worth of this pairing */ - switch(strategy) { - case 3: - /*s = "exact minimization";*/ - PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1); - cost = Fsave->count - PLA->F->count; - break; - case 2: - /*s = "full minimization";*/ - PLA->F = espresso(PLA->F, PLA->D, PLA->R); - cost = Fsave->count - PLA->F->count; - break; - case 1: - /*s = "strong division";*/ - PLA->F = reduce(PLA->F, PLA->D); - PLA->F = expand(PLA->F, PLA->R, FALSE); - PLA->F = irredundant(PLA->F, PLA->D); - cost = Fsave->count - PLA->F->count; - break; - case 0: - /*s = "weak division";*/ - mask = new_cube(); - set_or(mask, cube.var_mask[var1], cube.var_mask[var2]); - T = dist_merge(sf_save(PLA->F), mask); - cost = PLA->F->count - T->count; - sf_free(T); - set_free(mask); - } - - cost_array[var1][var2] = cost; - - if (strategy > 0) { - /* restore the original cube structure -- free the new ones */ - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = xnum_binary_vars; - cube.num_vars = xnum_vars; - cube.part_size = xpart_size; - cube_setup(); - - /* restore the original cover(s) -- free the new ones */ - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = Fsave; - PLA->D = Dsave; - PLA->R = Rsave; - } - } - } - - pair_free(PLA->pair); - PLA->pair = NULL; - return cost_array; -} - -static int best_cost; -static int **cost_array; -static ppair best_pair; -static pset best_phase; -static pPLA global_PLA; -static pcover best_F, best_D, best_R; -static int pair_minim_strategy; - - -print_pair(pair) -ppair pair; -{ - int i; - - printf("pair is"); - for(i = 0; i < pair->cnt; i++) - printf (" (%d %d)", pair->var1[i], pair->var2[i]); - printf("\n"); -} - - -int greedy_best_cost(cost_array_local, pair_p) -int **cost_array_local; -ppair *pair_p; -{ - int i, j, besti, bestj, maxcost, total_cost; - pset cand; - ppair pair; - - pair = pair_new(cube.num_binary_vars); - cand = set_full(cube.num_binary_vars); - total_cost = 0; - - while (set_ord(cand) >= 2) { - maxcost = -1; - for(i = 0; i < cube.num_binary_vars; i++) { - if (is_in_set(cand, i)) { - for(j = i+1; j < cube.num_binary_vars; j++) { - if (is_in_set(cand, j)) { - if (cost_array_local[i][j] > maxcost) { - maxcost = cost_array_local[i][j]; - besti = i; - bestj = j; - } - } - } - } - } - pair->var1[pair->cnt] = besti+1; - pair->var2[pair->cnt] = bestj+1; - pair->cnt++; - set_remove(cand, besti); - set_remove(cand, bestj); - total_cost += maxcost; - } - set_free(cand); - *pair_p = pair; - return total_cost; -} - - -ppair pair_best_cost(cost_array_local) -int **cost_array_local; -{ - ppair pair; - pset candidate; - - best_cost = -1; - best_pair = NULL; - cost_array = cost_array_local; - - pair = pair_new(cube.num_binary_vars); - candidate = set_full(cube.num_binary_vars); - generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost); - pair_free(pair); - set_free(candidate); - return best_pair; -} - - -int find_best_cost(pair) -register ppair pair; -{ - register int i, cost; - - cost = 0; - for(i = 0; i < pair->cnt; i++) - cost += cost_array[pair->var1[i]-1][pair->var2[i]-1]; - if (cost > best_cost) { - best_cost = cost; - best_pair = pair_save(pair, pair->cnt); - } - if ((debug & MINCOV) && trace) { - printf("cost is %d ", cost); - print_pair(pair); - } -} - -/* - pair_all: brute-force approach to try all possible pairings - - pair_strategy is: - 2) for espresso - 3) for minimize_exact - 4) for phase assignment -*/ - -pair_all(PLA, pair_strategy) -pPLA PLA; -int pair_strategy; -{ - ppair pair; - pset candidate; - - global_PLA = PLA; - pair_minim_strategy = pair_strategy; - best_cost = PLA->F->count + 1; - best_pair = NULL; - best_phase = NULL; - best_F = best_D = best_R = NULL; - pair = pair_new(cube.num_binary_vars); - candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars); - - generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair); - - pair_free(pair); - set_free(candidate); - - PLA->pair = best_pair; - PLA->phase = best_phase; -/* not really necessary - if (phase != NULL) - (void) set_phase(PLA->phase); -*/ - set_pair(PLA); - printf("# "); - print_pair(PLA->pair); - - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = best_F; - PLA->D = best_D; - PLA->R = best_R; -} - - -/* - * minimize_pair -- called as each pair is generated - */ -int minimize_pair(pair) -ppair pair; -{ - pcover Fsave, Dsave, Rsave; - int i, xnum_binary_vars, xnum_vars, *xpart_size; - - /* save the original covers */ - Fsave = sf_save(global_PLA->F); - Dsave = sf_save(global_PLA->D); - Rsave = sf_save(global_PLA->R); - - /* save the original cube structure */ - xnum_binary_vars = cube.num_binary_vars; - xnum_vars = cube.num_vars; - xpart_size = ALLOC(int, cube.num_vars); - for(i = 0; i < cube.num_vars; i++) - xpart_size[i] = cube.part_size[i]; - - /* setup the paired variables */ - global_PLA->pair = pair; - set_pair1(global_PLA, /* adjust_labels */ FALSE); - - /* call the minimizer */ - if (summary) - print_pair(pair); - switch(pair_minim_strategy) { - case 2: - EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F); - if (summary) - printf("# phase is %s\n", pc1(global_PLA->phase)); - break; - case 1: - EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D, - global_PLA->R, 1), "EXACT ", global_PLA->F); - break; - case 0: - EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D, - global_PLA->R), "ESPRESSO ", global_PLA->F); - break; - default: - break; - } - - /* see if we have a new best solution */ - if (global_PLA->F->count < best_cost) { - best_cost = global_PLA->F->count; - best_pair = pair_save(pair, pair->cnt); - best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL; - if (best_F != NULL) sf_free(best_F); - if (best_D != NULL) sf_free(best_D); - if (best_R != NULL) sf_free(best_R); - best_F = sf_save(global_PLA->F); - best_D = sf_save(global_PLA->D); - best_R = sf_save(global_PLA->R); - } - - /* restore the original cube structure -- free the new ones */ - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = xnum_binary_vars; - cube.num_vars = xnum_vars; - cube.part_size = xpart_size; - cube_setup(); - - /* restore the original cover(s) -- free the new ones */ - sf_free(global_PLA->F); - sf_free(global_PLA->D); - sf_free(global_PLA->R); - global_PLA->F = Fsave; - global_PLA->D = Dsave; - global_PLA->R = Rsave; - global_PLA->pair = NULL; - global_PLA->phase = NULL; -} - -generate_all_pairs(pair, n, candidate, action) -ppair pair; -int n; -pset candidate; -int (*action)(); -{ - int i, j; - pset recur_candidate; - ppair recur_pair; - - if (set_ord(candidate) < 2) { - (*action)(pair); - return 0; - } - - recur_pair = pair_save(pair, n); - recur_candidate = set_save(candidate); - - /* Find first variable still in the candidate set */ - for(i = 0; i < n; i++) - if (is_in_set(candidate, i)) - break; - - /* Try all pairs of i with other variables */ - for(j = i+1; j < n; j++) - if (is_in_set(candidate, j)) { - /* pair (i j) -- remove from candidate set for future pairings */ - set_remove(recur_candidate, i); - set_remove(recur_candidate, j); - - /* add to the pair array */ - recur_pair->var1[recur_pair->cnt] = i+1; - recur_pair->var2[recur_pair->cnt] = j+1; - recur_pair->cnt++; - - /* recur looking for the end ... */ - generate_all_pairs(recur_pair, n, recur_candidate, action); - - /* now break this pair, and restore candidate set */ - recur_pair->cnt--; - set_insert(recur_candidate, i); - set_insert(recur_candidate, j); - } - - /* if odd, generate all pairs which do NOT include i */ - if ((set_ord(candidate) % 2) == 1) { - set_remove(recur_candidate, i); - generate_all_pairs(recur_pair, n, recur_candidate, action); - } - - pair_free(recur_pair); - set_free(recur_candidate); -} - -ppair pair_new(n) -register int n; -{ - register ppair pair1; - - pair1 = ALLOC(pair_t, 1); - pair1->cnt = 0; - pair1->var1 = ALLOC(int, n); - pair1->var2 = ALLOC(int, n); - return pair1; -} - - -ppair pair_save(pair, n) -register ppair pair; -register int n; -{ - register int k; - register ppair pair1; - - pair1 = pair_new(n); - pair1->cnt = pair->cnt; - for(k = 0; k < pair->cnt; k++) { - pair1->var1[k] = pair->var1[k]; - pair1->var2[k] = pair->var2[k]; - } - return pair1; -} - - -int pair_free(pair) -register ppair pair; -{ - FREE(pair->var1); - FREE(pair->var2); - FREE(pair); -} diff --git a/src/benchmarks/espresso/part.c b/src/benchmarks/espresso/part.c deleted file mode 100644 index c2c2407..0000000 --- a/src/benchmarks/espresso/part.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - -static int visit_col(); - -static void -copy_row(A, prow) -register sm_matrix *A; -register sm_row *prow; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(A, p->row_num, p->col_num); - } -} - - -static int -visit_row(A, prow, rows_visited, cols_visited) -sm_matrix *A; -sm_row *prow; -int *rows_visited; -int *cols_visited; -{ - sm_element *p; - sm_col *pcol; - - if (! prow->flag) { - prow->flag = 1; - (*rows_visited)++; - if (*rows_visited == A->nrows) { - return 1; - } - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - if (! pcol->flag) { - if (visit_col(A, pcol, rows_visited, cols_visited)) { - return 1; - } - } - } - } - return 0; -} - - -static int -visit_col(A, pcol, rows_visited, cols_visited) -sm_matrix *A; -sm_col *pcol; -int *rows_visited; -int *cols_visited; -{ - sm_element *p; - sm_row *prow; - - if (! pcol->flag) { - pcol->flag = 1; - (*cols_visited)++; - if (*cols_visited == A->ncols) { - return 1; - } - for(p = pcol->first_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - if (! prow->flag) { - if (visit_row(A, prow, rows_visited, cols_visited)) { - return 1; - } - } - } - } - return 0; -} - -int -sm_block_partition(A, L, R) -sm_matrix *A; -sm_matrix **L, **R; -{ - int cols_visited, rows_visited; - register sm_row *prow; - register sm_col *pcol; - - /* Avoid the trivial case */ - if (A->nrows == 0) { - return 0; - } - - /* Reset the visited flags for each row and column */ - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - prow->flag = 0; - } - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - pcol->flag = 0; - } - - cols_visited = rows_visited = 0; - if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) { - /* we found all of the rows */ - return 0; - } else { - *L = sm_alloc(); - *R = sm_alloc(); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->flag) { - copy_row(*L, prow); - } else { - copy_row(*R, prow); - } - } - return 1; - } -} diff --git a/src/benchmarks/espresso/port.h b/src/benchmarks/espresso/port.h deleted file mode 100644 index d84a1b5..0000000 --- a/src/benchmarks/espresso/port.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef PORT_H -#define PORT_H - -#ifdef _WIN32 -#include <assert.h> -#include <stdio.h> -#endif - -#ifndef NULL -#define NULL 0 -#endif /* NULL */ - -#ifndef _WIN32 - -#ifdef SABER -#define volatile -#endif - -#ifdef _IBMR2 -#define _BSD -#ifndef _POSIX_SOURCE -#define _POSIX_SOURCE /* Argh! IBM strikes again */ -#endif -#ifndef _ALL_SOURCE -#define _ALL_SOURCE /* Argh! IBM strikes again */ -#endif -#ifndef _ANSI_C_SOURCE -#define _ANSI_C_SOURCE /* Argh! IBM strikes again */ -#endif -#endif - -/* - * int32 should be defined as the most economical sized integer capable of - * holding a 32 bit quantity - * int16 should be similarly defined - */ - -/* XXX hack */ -#ifndef MACHDEP_INCLUDED -#define MACHDEP_INCLUDED -#ifdef vax -typedef int int32; -typedef short int16; -#else - /* Ansi-C promises that these definitions should always work */ -typedef long int32; -typedef int int16; -#endif /* vax */ -#endif /* MACHDEP_INCLUDED */ - - -#ifndef __STDC__ -#ifndef __DATE__ -#ifdef CUR_DATE -#define __DATE__ CUR_DATE -#else -#define __DATE__ "unknown-date" -#endif /* CUR_DATE */ -#endif /* __DATE__ */ - -#ifndef __TIME__ -#ifdef CUR_TIME -#define __TIME__ CUR_TIME -#else -#define __TIME__ "unknown-time" -#endif /* CUR_TIME */ -#endif /* __TIME__ */ -#endif /* __STDC__ */ - -#ifdef sun386 -#define PORTAR -#endif - -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#undef HUGE -#include <math.h> -#include <signal.h> - -#if defined(ultrix) /* { */ -#if defined(_SIZE_T_) /* { */ -#define ultrix4 -#else /* } else { */ -#if defined(SIGLOST) /* { */ -#define ultrix3 -#else /* } else { */ -#define ultrix2 -#endif /* } */ -#endif /* } */ -#endif /* } */ - -#if defined(ultrix3) && defined(mips) -extern double rint(); -extern double trunc(); -#endif - -#if defined(sun) && defined(FD_SETSIZE) -#define sunos4 -#else -#define sunos3 -#endif - -#if defined(sequent) || defined(news800) -#define LACK_SYS5 -#endif - -#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) -#define SIGNAL_FN void -#else -/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */ -#define SIGNAL_FN int -#endif - -/* Some systems have 'fixed' certain functions which used to be int */ -#if defined(ultrix) || defined(SABER) || defined(hpux) || defined(aiws) || defined(apollo) || defined(__STDC__) -#define VOID_HACK void -#else -#define VOID_HACK int -#endif - -/* - * CHARBITS should be defined only if the compiler lacks "unsigned char". - * It should be a mask, e.g. 0377 for an 8-bit machine. - */ - -#ifndef CHARBITS -# define UNSCHAR(c) ((unsigned char)(c)) -#else -# define UNSCHAR(c) ((c)&CHARBITS) -#endif - -#define SIZET int - -#ifdef __STDC__ -#define CONST const -#define VOIDSTAR void * -#else -#define CONST -#define VOIDSTAR char * -#endif /* __STDC__ */ - - -/* Some machines fail to define some functions in stdio.h */ -#if !defined(__STDC__) && !defined(sprite) -extern FILE *popen(), *tmpfile(); -extern int pclose(); -#ifndef clearerr /* is a macro on many machines, but not all */ -extern VOID_HACK clearerr(); -#endif /* clearerr */ -#ifndef rewind -extern VOID_HACK rewind(); -#endif /* rewind */ -#endif /* __STDC__ */ - - -/* most machines don't give us a header file for these */ -#if defined(__STDC__) || defined(sprite) -#include <stdlib.h> -#else -#ifdef hpux -extern int abort(); -extern void free(), exit(), perror(); -#else -extern VOID_HACK abort(), free(), exit(), perror(); -#endif /* hpux */ -extern char *getenv(); -#ifdef ultrix4 -extern void *malloc(), *realloc(), *calloc(); -#else -extern char *malloc(), *realloc(), *calloc(); -#endif -#if defined(aiws) || defined(hpux) -extern int sprintf(); -#else -extern char *sprintf(); -#endif -extern int system(); -extern double atof(); -extern long atol(); -extern int sscanf(); -#endif /* __STDC__ */ - - -/* some call it strings.h, some call it string.h; others, also have memory.h */ -#if defined(__STDC__) || defined(sprite) -#include <string.h> -#else -/* ANSI C string.h -- 1/11/88 Draft Standard */ -#if defined(ultrix4) || defined(hpux) -#include <strings.h> -#else -extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror(); -extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr(); -extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn(); -extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset(); -extern int memcmp(), strcmp(); -#endif /* ultrix4 */ -#endif /* __STDC__ */ - -#ifdef lint -#undef putc /* correct lint '_flsbuf' bug */ -#endif /* lint */ - -/* a few extras */ -#if defined(hpux) -extern VOID_HACK srand(); -extern int rand(); -#define random() rand() -#define srandom(a) srand(a) -#define bzero(a,b) memset(a, 0, b) -#else -extern VOID_HACK srandom(); -extern long random(); -#endif - -/* -** _std_h is defined in /usr/local/lib/g++-include/std.h -*/ -#if ! defined(_std_h) -#if defined(ultrix3) || defined(ultrix4) || defined(hpux) -extern unsigned sleep(); -#else -extern VOID_HACK sleep(); -#endif -#endif /* _std_h */ -/* assertion macro */ - -#ifndef assert -#if defined(__STDC__) || defined(sprite) -#include <assert.h> -#else -#ifndef NDEBUG -#define assert(ex) {\ - if (! (ex)) {\ - (void) fprintf(stderr, "Assertion failed: file %s, line %d\n",\ - __FILE__, __LINE__);\ - (void) fflush(stdout);\ - abort();\ - }\ -} -#else -#define assert(ex) {;} -#endif -#endif -#endif - -/* handle the various limits */ -#if defined(__STDC__) || defined(POSIX) -#include <limits.h> -#else -#define USHRT_MAX (~ (unsigned short int) 0) -#define UINT_MAX (~ (unsigned int) 0) -#define ULONG_MAX (~ (unsigned long int) 0) -#define SHRT_MAX ((short int) (USHRT_MAX >> 1)) -#define INT_MAX ((int) (UINT_MAX >> 1)) -#define LONG_MAX ((long int) (ULONG_MAX >> 1)) -#endif - -#endif - -#endif /* PORT_H */ - diff --git a/src/benchmarks/espresso/primes.c b/src/benchmarks/espresso/primes.c deleted file mode 100644 index 7386784..0000000 --- a/src/benchmarks/espresso/primes.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "espresso.h" - -static bool primes_consensus_special_cases(); -static pcover primes_consensus_merge(); -static pcover and_with_cofactor(); - - -/* primes_consensus -- generate primes using consensus */ -pcover primes_consensus(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tnew, Tl, Tr; - - if (primes_consensus_special_cases(T, &Tnew) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - Tl = primes_consensus(scofactor(T, cl, best)); - Tr = primes_consensus(scofactor(T, cr, best)); - Tnew = primes_consensus_merge(Tl, Tr, cl, cr); - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - return Tnew; -} - -static bool -primes_consensus_special_cases(T, Tnew) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tnew = new_cover(0); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - free_cube(p); - - A = primes_consensus(T); - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - *Tnew = A; - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = cubeunlist(T); - *Tnew = sf_contain(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -static pcover -primes_consensus_merge(Tl, Tr, cl, cr) -pcover Tl, Tr; -pcube cl, cr; -{ - register pcube pl, pr, lastl, lastr, pt; - pcover T, Tsave; - - Tl = and_with_cofactor(Tl, cl); - Tr = and_with_cofactor(Tr, cr); - - T = sf_new(500, Tl->sf_size); - pt = T->data; - Tsave = sf_contain(sf_join(Tl, Tr)); - - foreach_set(Tl, lastl, pl) { - foreach_set(Tr, lastr, pr) { - if (cdist01(pl, pr) == 1) { - consensus(pt, pl, pr); - if (++T->count >= T->capacity) { - Tsave = sf_union(Tsave, sf_contain(T)); - T = sf_new(500, Tl->sf_size); - pt = T->data; - } else { - pt += T->wsize; - } - } - } - } - free_cover(Tl); - free_cover(Tr); - - Tsave = sf_union(Tsave, sf_contain(T)); - return Tsave; -} - - -static pcover -and_with_cofactor(A, cof) -pset_family A; -register pset cof; -{ - register pset last, p; - - foreach_set(A, last, p) { - INLINEset_and(p, p, cof); - if (cdist(p, cube.fullset) > 0) { - RESET(p, ACTIVE); - } else { - SET(p, ACTIVE); - } - } - return sf_inactive(A); -} diff --git a/src/benchmarks/espresso/reduce.c b/src/benchmarks/espresso/reduce.c deleted file mode 100644 index f818a2d..0000000 --- a/src/benchmarks/espresso/reduce.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - module: reduce.c - purpose: Perform the Espresso-II reduction step - - Reduction is a technique used to explore larger regions of the - optimization space. We replace each cube of F with a smaller - cube while still maintaining a cover of the same logic function. -*/ - -#include "espresso.h" - -static bool toggle = TRUE; - - -/* - reduce -- replace each cube in F with its reduction - - The reduction of a cube is the smallest cube contained in the cube - which can replace the cube in the original cover without changing - the cover. This is equivalent to the super cube of all of the - essential points in the cube. This can be computed directly. - - The problem is that the order in which the cubes are reduced can - greatly affect the final result. We alternate between two ordering - strategies: - - (1) Order the cubes in ascending order of distance from the - largest cube breaking ties by ordering cubes of equal distance - in descending order of size (sort_reduce) - - (2) Order the cubes in descending order of the inner-product of - the cube and the column sums (mini_sort) - - The real workhorse of this section is the routine SCCC which is - used to find the Smallest Cube Containing the Complement of a cover. - Reduction as proposed by Espresso-II takes a cube and computes its - maximal reduction as the intersection between the cube and the - smallest cube containing the complement of (F u D - {c}) cofactored - against c. - - As usual, the unate-recursive paradigm is used to compute SCCC. - The SCCC of a unate cover is trivial to compute, and thus we perform - Shannon Cofactor expansion attempting to drive the cover to be unate - as fast as possible. -*/ - -pcover reduce(F, D) -INOUT pcover F; -IN pcover D; -{ - register pcube last, p, cunder, *FD; - - /* Order the cubes */ - if (use_random_order) - F = random_order(F); - else { - F = toggle ? sort_reduce(F) : mini_sort(F, descend); - toggle = ! toggle; - } - - /* Try to reduce each cube */ - FD = cube2list(F, D); - foreach_set(F, last, p) { - cunder = reduce_cube(FD, p); /* reduce the cube */ - if (setp_equal(cunder, p)) { /* see if it actually did */ - SET(p, ACTIVE); /* cube remains active */ - SET(p, PRIME); /* cube remains prime ? */ - } else { - if (debug & REDUCE) { - printf("REDUCE: %s to %s %s\n", - pc1(p), pc2(cunder), print_time(ptime())); - } - set_copy(p, cunder); /* save reduced version */ - RESET(p, PRIME); /* cube is no longer prime */ - if (setp_empty(cunder)) - RESET(p, ACTIVE); /* if null, kill the cube */ - else - SET(p, ACTIVE); /* cube is active */ - } - free_cube(cunder); - } - free_cubelist(FD); - - /* Delete any cubes of F which reduced to the empty cube */ - return sf_inactive(F); -} - -/* reduce_cube -- find the maximal reduction of a cube */ -pcube reduce_cube(FD, p) -IN pcube *FD, p; -{ - pcube cunder; - - cunder = sccc(cofactor(FD, p)); - return set_and(cunder, cunder, p); -} - - -/* sccc -- find Smallest Cube Containing the Complement of a cover */ -pcube sccc(T) -INOUT pcube *T; /* T will be disposed of */ -{ - pcube r; - register pcube cl, cr; - register int best; - static int sccc_level = 0; - - if (debug & REDUCE1) { - debug_print(T, "SCCC", sccc_level++); - } - - if (sccc_special_cases(T, &r) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, REDUCE1); - r = sccc_merge(sccc(scofactor(T, cl, best)), - sccc(scofactor(T, cr, best)), cl, cr); - free_cubelist(T); - } - - if (debug & REDUCE1) - printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r)); - return r; -} - - -pcube sccc_merge(left, right, cl, cr) -INOUT register pcube left, right; /* will be disposed of ... */ -INOUT register pcube cl, cr; /* will be disposed of ... */ -{ - INLINEset_and(left, left, cl); - INLINEset_and(right, right, cr); - INLINEset_or(left, left, right); - free_cube(right); - free_cube(cl); - free_cube(cr); - return left; -} - - -/* - sccc_cube -- find the smallest cube containing the complement of a cube - - By DeMorgan's law and the fact that the smallest cube containing a - cover is the "or" of the positional cubes, it is simple to see that - the SCCC is the universe if the cube has more than two active - variables. If there is only a single active variable, then the - SCCC is merely the bitwise complement of the cube in that - variable. A last special case is no active variables, in which - case the SCCC is empty. - - This is "anded" with the incoming cube result. -*/ -pcube sccc_cube(result, p) -register pcube result, p; -{ - register pcube temp=cube.temp[0], mask; - int var; - - if ((var = cactive(p)) >= 0) { - mask = cube.var_mask[var]; - INLINEset_xor(temp, p, mask); - INLINEset_and(result, result, temp); - } - return result; -} - -/* - * sccc_special_cases -- check the special cases for sccc - */ - -bool sccc_special_cases(T, result) -INOUT pcube *T; /* will be disposed if answer is determined */ -OUT pcube *result; /* returned only if answer determined */ -{ - register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0]; - pcube *A, *B; - - /* empty cover => complement is universe => SCCC is universe */ - if (T[2] == NULL) { - *result = set_save(cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* row of 1's => complement is empty => SCCC is empty */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *result = new_cube(); - free_cubelist(T); - return TRUE; - } - } - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If cover is unate (or single cube), apply simple rules to find SCCCU */ - if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) { - *result = set_save(cube.fullset); - for(T1 = T+2; (p = *T1++) != NULL; ) { - (void) sccc_cube(*result, set_or(temp, p, cof)); - } - free_cubelist(T); - return TRUE; - } - - /* Check for column of 0's (which can be easily factored( */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - *result = sccc_cube(set_save(cube.fullset), ceil); - if (setp_equal(*result, cube.fullset)) { - free_cube(ceil); - } else { - *result = sccc_merge(sccc(cofactor(T,ceil)), - set_save(cube.fullset), ceil, *result); - } - free_cubelist(T); - return TRUE; - } - free_cube(ceil); - - /* Single active column at this point => tautology => SCCC is empty */ - if (cdata.vars_active == 1) { - *result = new_cube(); - free_cubelist(T); - return TRUE; - } - - /* Check for components */ - if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) { - if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) { - return MAYBE; - } else { - free_cubelist(T); - *result = sccc(A); - ceil = sccc(B); - (void) set_and(*result, *result, ceil); - set_free(ceil); - return TRUE; - } - } - - /* Not much we can do about it */ - return MAYBE; -} diff --git a/src/benchmarks/espresso/regex.h b/src/benchmarks/espresso/regex.h deleted file mode 100644 index be96614..0000000 --- a/src/benchmarks/espresso/regex.h +++ /dev/null @@ -1,269 +0,0 @@ -#if defined(hpux) -/* Definitions for data structures callers pass the regex library. - Copyright (C) 1985 Free Software Foundation, Inc. - - NO WARRANTY - - BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" -WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY -AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY -WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE -LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR -OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR -DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR -A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS -PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. - - GENERAL PUBLIC LICENSE TO COPY - - 1. You may copy and distribute verbatim copies of this source file -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy a valid copyright notice "Copyright -(C) 1985 Free Software Foundation, Inc."; and include following the -copyright notice a verbatim copy of the above disclaimer of warranty -and of this License. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of this source file or -any portion of it, and copy and distribute such modifications under -the terms of Paragraph 1 above, provided that you also do the following: - - a) cause the modified files to carry prominent notices stating - that you changed the files and the date of any change; and - - b) cause the whole of any work that you distribute or publish, - that in whole or in part contains or is a derivative of this - program or any part thereof, to be licensed at no charge to all - third parties on terms identical to those contained in this - License Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution fee for the physical act of - transferring a copy, and you may at your option offer warranty - protection in exchange for a fee. - -Mere aggregation of another unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute this program (or a portion or derivative -of it, under Paragraph 2) in object code or executable form under the terms -of Paragraphs 1 and 2 above provided that you also do one of the following: - - a) accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of - Paragraphs 1 and 2 above; or, - - b) accompany it with a written offer, valid for at least three - years, to give any third party free (except for a nominal - shipping charge) a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of - Paragraphs 1 and 2 above; or, - - c) accompany it with the information you received as to where the - corresponding source code may be obtained. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form alone.) - -For an executable file, complete source code means all the source code for -all modules it contains; but, as a special exception, it need not include -source code for modules which are standard libraries that accompany the -operating system on which the executable file runs. - - 4. You may not copy, sublicense, distribute or transfer this program -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer this program is void and -your rights to use the program under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full compliance. - - 5. If you wish to incorporate parts of this program into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet -worked out a simple rule that can be stated here, but we will often permit -this. We will be guided by the two goals of preserving the free status of -all derivatives of our free software and of promoting the sharing and reuse of -software. - - -In other words, you are welcome to use, share and improve this program. -You are forbidden to forbid anyone else to use, share and improve -what you give them. Help stamp out software-hoarding! */ - - -/* Define number of parens for which we record the beginnings and ends. - This affects how much space the `struct re_registers' type takes up. */ -#ifndef RE_NREGS -#define RE_NREGS 10 -#endif - -/* These bits are used in the obscure_syntax variable to choose among - alternative regexp syntaxes. */ - -/* 1 means plain parentheses serve as grouping, and backslash - parentheses are needed for literal searching. - 0 means backslash-parentheses are grouping, and plain parentheses - are for literal searching. */ -#define RE_NO_BK_PARENS 1 - -/* 1 means plain | serves as the "or"-operator, and \| is a literal. - 0 means \| serves as the "or"-operator, and | is a literal. */ -#define RE_NO_BK_VBAR 2 - -/* 0 means plain + or ? serves as an operator, and \+, \? are literals. - 1 means \+, \? are operators and plain +, ? are literals. */ -#define RE_BK_PLUS_QM 4 - -/* 1 means | binds tighter than ^ or $. - 0 means the contrary. */ -#define RE_TIGHT_VBAR 8 - -/* 1 means treat \n as an _OR operator - 0 means treat it as a normal character */ -#define RE_NEWLINE_OR 16 - -/* 0 means that a special characters (such as *, ^, and $) always have - their special meaning regardless of the surrounding context. - 1 means that special characters may act as normal characters in some - contexts. Specifically, this applies to: - ^ - only special at the beginning, or after ( or | - $ - only special at the end, or before ) or | - *, +, ? - only special when not after the beginning, (, or | */ -#define RE_CONTEXT_INDEP_OPS 32 - -/* Now define combinations of bits for the standard possibilities. */ -#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS) -#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR) -#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) -#define RE_SYNTAX_EMACS 0 - -/* This data structure is used to represent a compiled pattern. */ - -struct re_pattern_buffer - { - char *buffer; /* Space holding the compiled pattern commands. */ - int allocated; /* Size of space that buffer points to */ - int used; /* Length of portion of buffer actually occupied */ - char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ - /* re_search uses the fastmap, if there is one, - to skip quickly over totally implausible characters */ - char *translate; /* Translate table to apply to all characters before comparing. - Or zero for no translation. - The translation is applied to a pattern when it is compiled - and to data when it is matched. */ - char fastmap_accurate; - /* Set to zero when a new pattern is stored, - set to one when the fastmap is updated from it. */ - char can_be_null; /* Set to one by compiling fastmap - if this pattern might match the null string. - It does not necessarily match the null string - in that case, but if this is zero, it cannot. - 2 as value means can match null string - but at end of range or before a character - listed in the fastmap. */ - }; - -/* Structure to store "register" contents data in. - - Pass the address of such a structure as an argument to re_match, etc., - if you want this information back. - - start[i] and end[i] record the string matched by \( ... \) grouping i, - for i from 1 to RE_NREGS - 1. - start[0] and end[0] record the entire string matched. */ - -struct re_registers - { - int start[RE_NREGS]; - int end[RE_NREGS]; - }; - -/* These are the command codes that appear in compiled regular expressions, one per byte. - Some command codes are followed by argument bytes. - A command code can specify any interpretation whatever for its arguments. - Zero-bytes may appear in the compiled regular expression. */ - -enum regexpcode - { - unused, - exactn, /* followed by one byte giving n, and then by n literal bytes */ - begline, /* fails unless at beginning of line */ - endline, /* fails unless at end of line */ - jump, /* followed by two bytes giving relative address to jump to */ - on_failure_jump, /* followed by two bytes giving relative address of place - to resume at in case of failure. */ - finalize_jump, /* Throw away latest failure point and then jump to address. */ - maybe_finalize_jump, /* Like jump but finalize if safe to do so. - This is used to jump back to the beginning - of a repeat. If the command that follows - this jump is clearly incompatible with the - one at the beginning of the repeat, such that - we can be sure that there is no use backtracking - out of repetitions already completed, - then we finalize. */ - dummy_failure_jump, /* jump, and push a dummy failure point. - This failure point will be thrown away - if an attempt is made to use it for a failure. - A + construct makes this before the first repeat. */ - anychar, /* matches any one character */ - charset, /* matches any one char belonging to specified set. - First following byte is # bitmap bytes. - Then come bytes for a bit-map saying which chars are in. - Bits in each byte are ordered low-bit-first. - A character is in the set if its bit is 1. - A character too large to have a bit in the map - is automatically not in the set */ - charset_not, /* similar but match any character that is NOT one of those specified */ - start_memory, /* starts remembering the text that is matched - and stores it in a memory register. - followed by one byte containing the register number. - Register numbers must be in the range 0 through NREGS. */ - stop_memory, /* stops remembering the text that is matched - and stores it in a memory register. - followed by one byte containing the register number. - Register numbers must be in the range 0 through NREGS. */ - duplicate, /* match a duplicate of something remembered. - Followed by one byte containing the index of the memory register. */ - before_dot, /* Succeeds if before dot */ - at_dot, /* Succeeds if at dot */ - after_dot, /* Succeeds if after dot */ - begbuf, /* Succeeds if at beginning of buffer */ - endbuf, /* Succeeds if at end of buffer */ - wordchar, /* Matches any word-constituent character */ - notwordchar, /* Matches any char that is not a word-constituent */ - wordbeg, /* Succeeds if at word beginning */ - wordend, /* Succeeds if at word end */ - wordbound, /* Succeeds if at a word boundary */ - notwordbound, /* Succeeds if not at a word boundary */ - syntaxspec, /* Matches any character whose syntax is specified. - followed by a byte which contains a syntax code, Sword or such like */ - notsyntaxspec /* Matches any character whose syntax differs from the specified. */ - }; - -extern char *re_compile_pattern (); -/* Is this really advertised? */ -extern void re_compile_fastmap (); -extern int re_search (), re_search_2 (); -extern int re_match (), re_match_2 (); - -/* 4.2 bsd compatibility (yuck) */ -extern char *re_comp (); -extern int re_exec (); - -#ifdef SYNTAX_TABLE -extern char *re_syntax_table; -#endif -#endif diff --git a/src/benchmarks/espresso/rows.c b/src/benchmarks/espresso/rows.c deleted file mode 100644 index 6cb38ae..0000000 --- a/src/benchmarks/espresso/rows.c +++ /dev/null @@ -1,306 +0,0 @@ -#include "espresso.h" -#include "port.h" -#include "sparse_int.h" - - -/* - * allocate a new row vector - */ -sm_row * -sm_row_alloc() -{ - register sm_row *prow; - -#ifdef FAST_AND_LOOSE - if (sm_row_freelist == NIL(sm_row)) { - prow = ALLOC(sm_row, 1); - } else { - prow = sm_row_freelist; - sm_row_freelist = prow->next_row; - } -#else - prow = ALLOC(sm_row, 1); -#endif - - prow->row_num = 0; - prow->length = 0; - prow->first_col = prow->last_col = NIL(sm_element); - prow->next_row = prow->prev_row = NIL(sm_row); - prow->flag = 0; - prow->user_word = NIL(char); /* for our user ... */ - return prow; -} - - -/* - * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows; - * however, freeing a column must still walk down the column discarding - * the elements one-by-one; that is the only use for the extra '-DCOLS' - * compile flag ... - */ -void -sm_row_free(prow) -register sm_row *prow; -{ -#if defined(FAST_AND_LOOSE) && ! defined(COLS) - if (prow->first_col != NIL(sm_element)) { - /* Add the linked list of row items to the free list */ - prow->last_col->next_col = sm_element_freelist; - sm_element_freelist = prow->first_col; - } - - /* Add the row to the free list of rows */ - prow->next_row = sm_row_freelist; - sm_row_freelist = prow; -#else - register sm_element *p, *pnext; - - for(p = prow->first_col; p != 0; p = pnext) { - pnext = p->next_col; - sm_element_free(p); - } - FREE(prow); -#endif -} - - -/* - * duplicate an existing row - */ -sm_row * -sm_row_dup(prow) -register sm_row *prow; -{ - register sm_row *pnew; - register sm_element *p; - - pnew = sm_row_alloc(); - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_row_insert(pnew, p->col_num); - } - return pnew; -} - - -/* - * insert an element into a row vector - */ -sm_element * -sm_row_insert(prow, col) -register sm_row *prow; -register int col; -{ - register sm_element *test, *element; - - /* get a new item, save its address */ - sm_element_alloc(element); - test = element; - sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, - next_col, prev_col, col_num, col, test); - - /* if item was not used, free it */ - if (element != test) { - sm_element_free(element); - } - - /* either way, return the current new value */ - return test; -} - - -/* - * remove an element from a row vector - */ -void -sm_row_remove(prow, col) -register sm_row *prow; -register int col; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) - ; - if (p != 0 && p->col_num == col) { - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - sm_element_free(p); - } -} - - -/* - * find an element (if it is in the row vector) - */ -sm_element * -sm_row_find(prow, col) -sm_row *prow; -int col; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) - ; - if (p != 0 && p->col_num == col) { - return p; - } else { - return NIL(sm_element); - } -} - -/* - * return 1 if row p2 contains row p1; 0 otherwise - */ -int -sm_row_contains(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - while (q1 != 0) { - if (q2 == 0 || q1->col_num < q2->col_num) { - return 0; - } else if (q1->col_num == q2->col_num) { - q1 = q1->next_col; - q2 = q2->next_col; - } else { - q2 = q2->next_col; - } - } - return 1; -} - - -/* - * return 1 if row p1 and row p2 share an element in common - */ -int -sm_row_intersects(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - if (q1 == 0 || q2 == 0) return 0; - for(;;) { - if (q1->col_num < q2->col_num) { - if ((q1 = q1->next_col) == 0) { - return 0; - } - } else if (q1->col_num > q2->col_num) { - if ((q2 = q2->next_col) == 0) { - return 0; - } - } else { - return 1; - } - } -} - - -/* - * compare two rows, lexical ordering - */ -int -sm_row_compare(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - while(q1 != 0 && q2 != 0) { - if (q1->col_num != q2->col_num) { - return q1->col_num - q2->col_num; - } - q1 = q1->next_col; - q2 = q2->next_col; - } - - if (q1 != 0) { - return 1; - } else if (q2 != 0) { - return -1; - } else { - return 0; - } -} - - -/* - * return the intersection - */ -sm_row * -sm_row_and(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - register sm_row *result; - - result = sm_row_alloc(); - q1 = p1->first_col; - q2 = p2->first_col; - if (q1 == 0 || q2 == 0) return result; - for(;;) { - if (q1->col_num < q2->col_num) { - if ((q1 = q1->next_col) == 0) { - return result; - } - } else if (q1->col_num > q2->col_num) { - if ((q2 = q2->next_col) == 0) { - return result; - } - } else { - (void) sm_row_insert(result, q1->col_num); - if ((q1 = q1->next_col) == 0) { - return result; - } - if ((q2 = q2->next_col) == 0) { - return result; - } - } - } -} - -int -sm_row_hash(prow, modulus) -sm_row *prow; -int modulus; -{ - register int sum; - register sm_element *p; - - sum = 0; - for(p = prow->first_col; p != 0; p = p->next_col) { - sum = (sum*17 + p->col_num) % modulus; - } - return sum; -} - -/* - * remove an element from a row vector (given a pointer to the element) - */ -void -sm_row_remove_element(prow, p) -register sm_row *prow; -register sm_element *p; -{ - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - sm_element_free(p); -} - - -void -sm_row_print(fp, prow) -FILE *fp; -sm_row *prow; -{ - sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) fprintf(fp, " %d", p->col_num); - } -} diff --git a/src/benchmarks/espresso/set.c b/src/benchmarks/espresso/set.c deleted file mode 100644 index 4c6ad15..0000000 --- a/src/benchmarks/espresso/set.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * set.c -- routines for maniuplating sets and set families - */ - -/* LINTLIBRARY */ - -#include "espresso.h" -static pset_family set_family_garbage = NULL; - -static int intcpy(d, s, n) -register unsigned int *d, *s; -register long n; -{ - register int i; - for(i = 0; i < n; i++) { - *d++ = *s++; - } -} - - -/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */ -int bit_index(a) -register unsigned int a; -{ - register int i; - if (a == 0) - return -1; - for(i = 0; (a & 1) == 0; a >>= 1, i++) - ; - return i; -} - - -/* set_ord -- count number of elements in a set */ -int set_ord(a) -register pset a; -{ - register int i, sum = 0; - register unsigned int val; - for(i = LOOP(a); i > 0; i--) - if ((val = a[i]) != 0) - sum += count_ones(val); - return sum; -} - -/* set_dist -- distance between two sets (# elements in common) */ -int set_dist(a, b) -register pset a, b; -{ - register int i, sum = 0; - register unsigned int val; - for(i = LOOP(a); i > 0; i--) - if ((val = a[i] & b[i]) != 0) - sum += count_ones(val); - return sum; -} - -/* set_clear -- make "r" the empty set of "size" elements */ -pset set_clear(r, size) -register pset r; -int size; -{ - register int i = LOOPINIT(size); - *r = i; do r[i] = 0; while (--i > 0); - return r; -} - -/* set_fill -- make "r" the universal set of "size" elements */ -pset set_fill(r, size) -register pset r; -register int size; -{ - register int i = LOOPINIT(size); - *r = i; - r[i] = ~ (unsigned) 0; - r[i] >>= i * BPI - size; - while (--i > 0) - r[i] = ~ (unsigned) 0; - return r; -} - -/* set_copy -- copy set a into set r */ -pset set_copy(r, a) -register pset r, a; -{ - register int i = LOOPCOPY(a); - do r[i] = a[i]; while (--i >= 0); - return r; -} - -/* set_and -- compute intersection of sets "a" and "b" */ -pset set_and(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0); - return r; -} - -/* set_or -- compute union of sets "a" and "b" */ -pset set_or(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0); - return r; -} - -/* set_diff -- compute difference of sets "a" and "b" */ -pset set_diff(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0); - return r; -} - -/* set_xor -- compute exclusive-or of sets "a" and "b" */ -pset set_xor(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); -#ifdef IBM_WATC - PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0); -#else - PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0); -#endif - return r; -} - -/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */ -pset set_merge(r, a, b, mask) -register pset r, a, b, mask; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0); - return r; -} - -/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */ -bool set_andp(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - register unsigned int x = 0; - PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0); - return x != 0; -} - -/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */ -bool set_orp(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - register unsigned int x = 0; - PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0); - return x != 0; -} - -/* setp_empty -- check if the set "a" is empty */ -bool setp_empty(a) -register pset a; -{ - register int i = LOOP(a); - do if (a[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_full -- check if the set "a" is the full set of "size" elements */ -bool setp_full(a, size) -register pset a; -register int size; -{ - register int i = LOOP(a); - register unsigned int test; - test = ~ (unsigned) 0; - test >>= i * BPI - size; - if (a[i] != test) - return FALSE; - while (--i > 0) - if (a[i] != (~(unsigned) 0)) - return FALSE; - return TRUE; -} - -/* setp_equal -- check if the set "a" equals set "b" */ -bool setp_equal(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] != b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_disjoint -- check if intersection of "a" and "b" is empty */ -bool setp_disjoint(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] & b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_implies -- check if "a" implies "b" ("b" contains "a") */ -bool setp_implies(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] & ~b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* sf_or -- form the "or" of all sets in a set family */ -pset sf_or(A) -pset_family A; -{ - register pset or, last, p; - - or = set_new(A->sf_size); - foreach_set(A, last, p) - INLINEset_or(or, or, p); - return or; -} - -/* sf_and -- form the "and" of all sets in a set family */ -pset sf_and(A) -pset_family A; -{ - register pset and, last, p; - - and = set_fill(set_new(A->sf_size), A->sf_size); - foreach_set(A, last, p) - INLINEset_and(and, and, p); - return and; -} - -/* sf_active -- make all members of the set family active */ -pset_family sf_active(A) -pset_family A; -{ - register pset p, last; - foreach_set(A, last, p) { - SET(p, ACTIVE); - } - A->active_count = A->count; - return A; -} - - -/* sf_inactive -- remove all inactive cubes in a set family */ -pset_family sf_inactive(A) -pset_family A; -{ - register pset p, last, pdest; - - pdest = A->data; - foreach_set(A, last, p) { - if (TESTP(p, ACTIVE)) { - if (pdest != p) { - INLINEset_copy(pdest, p); - } - pdest += A->wsize; - } else { - A->count--; - } - } - return A; -} - - -/* sf_copy -- copy a set family */ -pset_family sf_copy(R, A) -pset_family R, A; -{ - R->sf_size = A->sf_size; - R->wsize = A->wsize; -/*R->capacity = A->count;*/ -/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/ - R->count = A->count; - R->active_count = A->active_count; - intcpy(R->data, A->data, (long) A->wsize * A->count); - return R; -} - - -/* sf_join -- join A and B into a single set_family */ -pset_family sf_join(A, B) -pset_family A, B; -{ - pset_family R; - long asize = A->count * A->wsize; - long bsize = B->count * B->wsize; - - if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch"); - R = sf_new(A->count + B->count, A->sf_size); - R->count = A->count + B->count; - R->active_count = A->active_count + B->active_count; - intcpy(R->data, A->data, asize); - intcpy(R->data + asize, B->data, bsize); - return R; -} - - -/* sf_append -- append the sets of B to the end of A, and dispose of B */ -pset_family sf_append(A, B) -pset_family A, B; -{ - long asize = A->count * A->wsize; - long bsize = B->count * B->wsize; - - if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch"); - A->capacity = A->count + B->count; - A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); - intcpy(A->data + asize, B->data, bsize); - A->count += B->count; - A->active_count += B->active_count; - sf_free(B); - return A; -} - - -/* sf_new -- allocate "num" sets of "size" elements each */ -pset_family sf_new(num, size) -int num, size; -{ - pset_family A; - if (set_family_garbage == NULL) { - A = ALLOC(set_family_t, 1); - } else { - A = set_family_garbage; - set_family_garbage = A->next; - } - A->sf_size = size; - A->wsize = SET_SIZE(size); - A->capacity = num; - A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize); - A->count = 0; - A->active_count = 0; - return A; -} - - -/* sf_save -- create a duplicate copy of a set family */ -pset_family sf_save(A) -register pset_family A; -{ - return sf_copy(sf_new(A->count, A->sf_size), A); -} - - -/* sf_free -- free the storage allocated for a set family */ -void sf_free(A) -pset_family A; -{ - FREE(A->data); - A->next = set_family_garbage; - set_family_garbage = A; -} - - -/* sf_cleanup -- free all of the set families from the garbage list */ -void sf_cleanup() -{ - register pset_family p, pnext; - for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) { - pnext = p->next; - FREE(p); - } - set_family_garbage = (pset_family) NULL; -} - - -/* sf_addset -- add a set to the end of a set family */ -pset_family sf_addset(A, s) -pset_family A; -pset s; -{ - register pset p; - - if (A->count >= A->capacity) { - A->capacity = A->capacity + A->capacity/2 + 1; - A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); - } - p = GETSET(A, A->count++); - INLINEset_copy(p, s); - return A; -} - -/* sf_delset -- delete a set from a set family */ -void sf_delset(A, i) -pset_family A; -int i; -{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));} - -/* sf_print -- print a set_family as a set (list the element numbers) */ -void sf_print(A) -pset_family A; -{ - char *ps1(); - register pset p; - register int i; - foreachi_set(A, i, p) - printf("A[%d] = %s\n", i, ps1(p)); -} - -/* sf_bm_print -- print a set_family as a bit-matrix */ -void sf_bm_print(A) -pset_family A; -{ - char *pbv1(); - register pset p; - register int i; - foreachi_set(A, i, p) - printf("[%4d] %s\n", i, pbv1(p, A->sf_size)); -} - - -/* sf_write -- output a set family in an unintelligable manner */ -void sf_write(fp, A) -FILE *fp; -pset_family A; -{ - register pset p, last; - fprintf(fp, "%d %d\n", A->count, A->sf_size); - foreach_set(A, last, p) - set_write(fp, p); - (void) fflush(fp); -} - - -/* sf_read -- read a set family written by sf_write */ -pset_family sf_read(fp) -FILE *fp; -{ - int i, j; - register pset p, last; - pset_family A; - - (void) fscanf(fp, "%d %d\n", &i, &j); - A = sf_new(i, j); - A->count = i; - foreach_set(A, last, p) { - (void) fscanf(fp, "%x", p); - for(j = 1; j <= LOOP(p); j++) - (void) fscanf(fp, "%x", p+j); - } - return A; -} - - -/* set_write -- output a set in an unintelligable manner */ -void set_write(fp, a) -register FILE *fp; -register pset a; -{ - register int n = LOOP(a), j; - - for(j = 0; j <= n; j++) { - fprintf(fp, "%x ", a[j]); - if ((j+1) % 8 == 0 && j != n) - fprintf(fp, "\n\t"); - } - fprintf(fp, "\n"); -} - - -/* sf_bm_read -- read a set family written by sf_bm_print (almost) */ -pset_family sf_bm_read(fp) -FILE *fp; -{ - int i, j, rows, cols; - register pset pdest; - pset_family A; - - (void) fscanf(fp, "%d %d\n", &rows, &cols); - A = sf_new(rows, cols); - for(i = 0; i < rows; i++) { - pdest = GETSET(A, A->count++); - (void) set_clear(pdest, A->sf_size); - for(j = 0; j < cols; j++) { - switch(getc(fp)) { - case '0': - break; - case '1': - set_insert(pdest, j); - break; - default: - fatal("Error reading set family"); - } - } - if (getc(fp) != '\n') { - fatal("Error reading set family (at end of line)"); - } - } - return A; -} - - - -/* ps1 -- convert a set into a printable string */ -#define largest_string 120 -static char s1[largest_string]; -char *ps1(a) -register pset a; -{ - register int i, num, l, len = 0, n = NELEM(a); - char temp[20]; - bool first = TRUE; - - s1[len++] = '['; - for(i = 0; i < n; i++) - if (is_in_set(a,i)) { - if (! first) - s1[len++] = ','; - first = FALSE; num = i; - /* Generate digits (reverse order) */ - l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0); - /* Copy them back in correct order */ - do s1[len++] = temp[--l]; while (l > 0); - if (len > largest_string-15) { - s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.'; - break; - } - } - - s1[len++] = ']'; - s1[len++] = '\0'; - return s1; -} - -/* pbv1 -- print bit-vector */ -char *pbv1(s, n) -pset s; -int n; -{ - register int i; - for(i = 0; i < n; i++) - s1[i] = is_in_set(s,i) ? '1' : '0'; - s1[n] = '\0'; - return s1; -} - - -/* set_adjcnt -- adjust the counts for a set by "weight" */ -void -set_adjcnt(a, count, weight) -register pset a; -register int *count, weight; -{ - register int i, base; - register unsigned int val; - - for(i = LOOP(a); i > 0; ) { - for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { - if (val & 1) { - count[base] += weight; - } - } - } -} - - - -/* sf_count -- perform a column sum over a set family */ -int *sf_count(A) -pset_family A; -{ - register pset p, last; - register int i, base, *count; - register unsigned int val; - - count = ALLOC(int, A->sf_size); - for(i = A->sf_size - 1; i >= 0; i--) { - count[i] = 0; - } - - foreach_set(A, last, p) { - for(i = LOOP(p); i > 0; ) { - for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { - if (val & 1) { - count[base]++; - } - } - } - } - return count; -} - - -/* sf_count_restricted -- perform a column sum over a set family, restricting - * to only the columns which are in r; also, the columns are weighted by the - * number of elements which are in each row - */ -int *sf_count_restricted(A, r) -pset_family A; -register pset r; -{ - register pset p; - register int i, base, *count; - register unsigned int val; - int weight; - pset last; - - count = ALLOC(int, A->sf_size); - for(i = A->sf_size - 1; i >= 0; i--) { - count[i] = 0; - } - - /* Loop for each set */ - foreach_set(A, last, p) { - weight = 1024 / (set_ord(p) - 1); - for(i = LOOP(p); i > 0; ) { - for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) { - if (val & 1) { - count[base] += weight; - } - } - } - } - return count; -} - - -/* - * sf_delc -- delete columns first ... last of A - */ -pset_family sf_delc(A, first, last) -pset_family A; -int first, last; -{ - return sf_delcol(A, first, last-first + 1); -} - - -/* - * sf_addcol -- add columns to a set family; includes a quick check to see - * if there is already enough room (and hence, can avoid copying) - */ -pset_family sf_addcol(A, firstcol, n) -pset_family A; -int firstcol, n; -{ - int maxsize; - - /* Check if adding columns at the end ... */ - if (firstcol == A->sf_size) { - /* If so, check if there is already enough room */ - maxsize = BPI * LOOPINIT(A->sf_size); - if ((A->sf_size + n) <= maxsize) { - A->sf_size += n; - return A; - } - } - return sf_delcol(A, firstcol, -n); -} - -/* - * sf_delcol -- add/delete columns to/from a set family - * - * if n > 0 then n columns starting from firstcol are deleted if n < 0 - * then n blank columns are inserted starting at firstcol - * (i.e., the first new column number is firstcol) - * - * This is done by copying columns in the array which is a relatively - * slow operation. - */ -pset_family sf_delcol(A, firstcol, n) -pset_family A; -register int firstcol, n; -{ - register pset p, last, pdest; - register int i; - pset_family B; - - B = sf_new(A->count, A->sf_size - n); - foreach_set(A, last, p) { - pdest = GETSET(B, B->count++); - INLINEset_clear(pdest, B->sf_size); - for(i = 0; i < firstcol; i++) - if (is_in_set(p, i)) - set_insert(pdest, i); - for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++) - if (is_in_set(p, i)) - set_insert(pdest, i - n); - } - sf_free(A); - return B; -} - - -/* - * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst" - */ -pset_family sf_copy_col(dst, dstcol, src, srccol) -pset_family dst, src; -int dstcol, srccol; -{ - register pset last, p, pdest; - register int word_test, word_set; - unsigned int bit_set, bit_test; - - /* CHEAT! form these constants outside the loop */ - word_test = WHICH_WORD(srccol); - bit_test = 1 << WHICH_BIT(srccol); - word_set = WHICH_WORD(dstcol); - bit_set = 1 << WHICH_BIT(dstcol); - - pdest = dst->data; - foreach_set(src, last, p) { - if ((p[word_test] & bit_test) != 0) - pdest[word_set] |= bit_set; -/* - * equivalent code for this is ... - * if (is_in_set(p, srccol)) set_insert(pdest, destcol); - */ - pdest += dst->wsize; - } - return dst; -} - - - -/* - * sf_compress -- delete columns from a matrix - */ -pset_family sf_compress(A, c) -pset_family A; /* will be freed */ -register pset c; -{ - register pset p; - register int i, bcol; - pset_family B; - - /* create a clean set family for the result */ - B = sf_new(A->count, set_ord(c)); - for(i = 0; i < A->count; i++) { - p = GETSET(B, B->count++); - INLINEset_clear(p, B->sf_size); - } - - /* copy each column of A which has a 1 in c */ - bcol = 0; - for(i = 0; i < A->sf_size; i++) { - if (is_in_set(c, i)) { - (void) sf_copy_col(B, bcol++, A, i); - } - } - sf_free(A); - return B; -} - - - -/* - * sf_transpose -- transpose a bit matrix - * - * There are trickier ways of doing this, but this works. - */ -pset_family sf_transpose(A) -pset_family A; -{ - pset_family B; - register pset p; - register int i, j; - - B = sf_new(A->sf_size, A->count); - B->count = A->sf_size; - foreachi_set(B, i, p) { - INLINEset_clear(p, B->sf_size); - } - foreachi_set(A, i, p) { - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(p, j)) { - set_insert(GETSET(B, j), i); - } - } - } - sf_free(A); - return B; -} - - -/* - * sf_permute -- permute the columns of a set_family - * - * permute is an array of integers containing column numbers of A which - * are to be retained. - */ -pset_family sf_permute(A, permute, npermute) -pset_family A; -register int *permute, npermute; -{ - pset_family B; - register pset p, last, pdest; - register int j; - - B = sf_new(A->count, npermute); - B->count = A->count; - foreach_set(B, last, p) - INLINEset_clear(p, npermute); - - pdest = B->data; - foreach_set(A, last, p) { - for(j = 0; j < npermute; j++) - if (is_in_set(p, permute[j])) - set_insert(pdest, j); - pdest += B->wsize; - } - sf_free(A); - return B; -} diff --git a/src/benchmarks/espresso/setc.c b/src/benchmarks/espresso/setc.c deleted file mode 100644 index a2d06c9..0000000 --- a/src/benchmarks/espresso/setc.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - setc.c -- massive bit-hacking for performing special "cube"-type - operations on a set - - The basic trick used for binary valued variables is the following: - - If a[w] and b[w] contain a full word of binary variables, then: - - 1) to get the full word of their intersection, we use - - x = a[w] & b[w]; - - - 2) to see if the intersection is null in any variables, we examine - - x = ~(x | x >> 1) & DISJOINT; - - this will have a single 1 in each binary variable for which - the intersection is null. In particular, if this is zero, - then there are no disjoint variables; or, if this is nonzero, - then there is at least one disjoint variable. A "count_ones" - over x will tell in how many variables they have an null - intersection. - - - 3) to get a mask which selects the disjoint variables, we use - - (x | x << 1) - - this provides a selector which can be used to see where - they have an null intersection - - - cdist return distance between two cubes - cdist0 return true if two cubes are distance 0 apart - cdist01 return distance, or 2 if distance exceeds 1 - consensus compute consensus of two cubes distance 1 apart - force_lower expand hack (for now), related to consensus -*/ - -#include "espresso.h" - -/* see if the cube has a full row of 1's (with respect to cof) */ -bool full_row(p, cof) -IN register pcube p, cof; -{ - register int i = LOOP(p); - do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* - cdist0 -- return TRUE if a and b are distance 0 apart -*/ - -bool cdist0(a, b) -register pcube a, b; -{ - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (~(x | x >> 1) & cube.inmask) - return FALSE; /* disjoint in some variable */ - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (~(x | x >> 1) & DISJOINT) - return FALSE; /* disjoint in some variable */ - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - return FALSE; /* disjoint in this variable */ - nextvar: ; - } - } - return TRUE; -} - -/* - cdist01 -- return the "distance" between two cubes (defined as the - number of null variables in their intersection). If the distance - exceeds 1, the value 2 is returned. -*/ - -int cdist01(a, b) -register pset a, b; -{ - int dist = 0; - - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~ (x | x >> 1) & cube.inmask) - if ((dist = count_ones(x)) > 1) - return 2; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~ (x | x >> 1) & DISJOINT) - if (dist == 1 || (dist += count_ones(x)) > 1) - return 2; - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - if (++dist > 1) - return 2; - nextvar: ; - } - } - return dist; -} - -/* - cdist -- return the "distance" between two cubes (defined as the - number of null variables in their intersection). -*/ - -int cdist(a, b) -register pset a, b; -{ - int dist = 0; - - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~ (x | x >> 1) & cube.inmask) - dist = count_ones(x); - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~ (x | x >> 1) & DISJOINT) - dist += count_ones(x); - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - dist++; - nextvar: ; - } - } - return dist; -} - -/* - force_lower -- Determine which variables of a do not intersect b. -*/ - -pset force_lower(xlower, a, b) -INOUT pset xlower; -IN register pset a, b; -{ - - { /* Check binary variables (if any) */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~(x | x >> 1) & cube.inmask) - xlower[last] |= (x | (x << 1)) & a[last]; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~(x | x >> 1) & DISJOINT) - xlower[w] |= (x | (x << 1)) & a[w]; - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - for(w = cube.first_word[var]; w <= last; w++) - xlower[w] |= a[w] & mask[w]; - nextvar: ; - } - } - return xlower; -} - -/* - consensus -- multiple-valued consensus - - Although this looks very messy, the idea is to compute for r the - "and" of the cubes a and b for each variable, unless the "and" is - null in a variable, in which case the "or" of a and b is computed - for this variable. - - Because we don't check how many variables are null in the - intersection of a and b, the returned value for r really only - represents the consensus when a and b are distance 1 apart. -*/ - -void consensus(r, a, b) -INOUT pcube r; -IN register pcube a, b; -{ - INLINEset_clear(r, cube.size); - - { /* Check binary variables (if any) */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - r[last] = x = a[last] & b[last]; - if (x = ~(x | x >> 1) & cube.inmask) - r[last] |= (x | (x << 1)) & (a[last] | b[last]); - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - r[w] = x = a[w] & b[w]; - if (x = ~(x | x >> 1) & DISJOINT) - r[w] |= (x | (x << 1)) & (a[w] | b[w]); - } - } - } - - - { /* Check the multiple-valued variables */ - bool empty; int var; unsigned int x; - register int w, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - last = cube.last_word[var]; - empty = TRUE; - for(w = cube.first_word[var]; w <= last; w++) - if (x = a[w] & b[w] & mask[w]) - empty = FALSE, r[w] |= x; - if (empty) - for(w = cube.first_word[var]; w <= last; w++) - r[w] |= mask[w] & (a[w] | b[w]); - } - } -} - -/* - cactive -- return the index of the single active variable in - the cube, or return -1 if there are none or more than 2. -*/ - -int cactive(a) -register pcube a; -{ - int active = -1, dist = 0, bit_index(); - - { /* Check binary variables */ - register int w, last; - register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last]; - if (x = ~ (x & x >> 1) & cube.inmask) { - if ((dist = count_ones(x)) > 1) - return -1; /* more than 2 active variables */ - active = (last-1)*(BPI/2) + bit_index(x) / 2; - } - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w]; - if (x = ~ (x & x >> 1) & DISJOINT) { - if ((dist += count_ones(x)) > 1) - return -1; /* more than 2 active variables */ - active = (w-1)*(BPI/2) + bit_index(x) / 2; - } - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; - register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~ a[w]) { - if (++dist > 1) - return -1; - active = var; - break; - } - } - } - return active; -} - -/* - ccommon -- return TRUE if a and b are share "active" variables - active variables include variables that are empty; -*/ - -bool ccommon(a, b, cof) -register pcube a, b, cof; -{ - { /* Check binary variables */ - int last; - register int w; - register unsigned int x, y; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] | cof[last]; - y = b[last] | cof[last]; - if (~(x & x>>1) & ~(y & y>>1) & cube.inmask) - return TRUE; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] | cof[w]; - y = b[w] | cof[w]; - if (~(x & x>>1) & ~(y & y>>1) & DISJOINT) - return TRUE; - } - } - } - - { /* Check the multiple-valued variables */ - int var; - register int w, last; - register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - /* Check for some part missing from a */ - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~a[w] & ~cof[w]) { - - /* If so, check for some part missing from b */ - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~b[w] & ~cof[w]) - return TRUE; /* both active */ - break; - } - } - } - return FALSE; -} - -/* - These routines compare two sets (cubes) for the qsort() routine and - return: - - -1 if set a is to precede set b - 0 if set a and set b are equal - 1 if set a is to follow set b - - Usually the SIZE field of the set is assumed to contain the size - of the set (which will save recomputing the set size during the - sort). For distance-1 merging, the global variable cube.temp[0] is - a mask which mask's-out the merging variable. -*/ - -/* descend -- comparison for descending sort on set size */ -int descend(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - if (SIZE(a1) > SIZE(b1)) return -1; - else if (SIZE(a1) < SIZE(b1)) return 1; - else { - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; - while (--i > 0); - } - return 0; -} - -/* ascend -- comparison for ascending sort on set size */ -int ascend(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - if (SIZE(a1) > SIZE(b1)) return 1; - else if (SIZE(a1) < SIZE(b1)) return -1; - else { - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1; - while (--i > 0); - } - return 0; -} - - -/* lex_order -- comparison for "lexical" ordering of cubes */ -int lex_order(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; - while (--i > 0); - return 0; -} - - -/* d1_order -- comparison for distance-1 merge routine */ -int d1_order(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b, c1 = cube.temp[0]; - register int i = LOOP(a1); - register unsigned int x1, x2; - do - if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1; - else if (x1 < x2) return 1; - while (--i > 0); - return 0; -} - - -/* desc1 -- comparison (without indirection) for descending sort */ -/* also has effect of handling NULL pointers,and a NULL pointer has smallest -order */ -int desc1(a, b) -register pset a, b; -{ - if (a == (pset) NULL) - return (b == (pset) NULL) ? 0 : 1; - else if (b == (pset) NULL) - return -1; - if (SIZE(a) > SIZE(b)) return -1; - else if (SIZE(a) < SIZE(b)) return 1; - else { - register int i = LOOP(a); - do - if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1; - while (--i > 0); - } - return 0; -} diff --git a/src/benchmarks/espresso/sharp.c b/src/benchmarks/espresso/sharp.c deleted file mode 100644 index 24401df..0000000 --- a/src/benchmarks/espresso/sharp.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - sharp.c -- perform sharp, disjoint sharp, and intersection -*/ - -#include "espresso.h" - -long start_time; - - -/* cv_sharp -- form the sharp product between two covers */ -pcover cv_sharp(A, B) -pcover A, B; -{ - pcube last, p; - pcover T; - - T = new_cover(0); - foreach_set(A, last, p) - T = sf_union(T, cb_sharp(p, B)); - return T; -} - - -/* cb_sharp -- form the sharp product between a cube and a cover */ -pcover cb_sharp(c, T) -pcube c; -pcover T; -{ - if (T->count == 0) { - T = sf_addset(new_cover(1), c); - } else { - start_time = ptime(); - T = cb_recur_sharp(c, T, 0, T->count-1, 0); - } - return T; -} - - -/* recursive formulation to provide balanced merging */ -pcover cb_recur_sharp(c, T, first, last, level) -pcube c; -pcover T; -int first, last, level; -{ - pcover temp, left, right; - int middle; - - if (first == last) { - temp = sharp(c, GETSET(T, first)); - } else { - middle = (first + last) / 2; - left = cb_recur_sharp(c, T, first, middle, level+1); - right = cb_recur_sharp(c, T, middle+1, last, level+1); - temp = cv_intersect(left, right); - if ((debug & SHARP) && level < 4) { - printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n", - level, temp->count, left->count, right->count, - print_time(ptime() - start_time)); - (void) fflush(stdout); - } - free_cover(left); - free_cover(right); - } - return temp; -} - - -/* sharp -- form the sharp product between two cubes */ -pcover sharp(a, b) -pcube a, b; -{ - register int var; - register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2]; - pcover r = new_cover(cube.num_vars); - - if (cdist0(a, b)) { - set_diff(d, a, b); - for(var = 0; var < cube.num_vars; var++) { - if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) { - set_diff(temp1, a, cube.var_mask[var]); - set_or(GETSET(r, r->count++), temp, temp1); - } - } - } else { - r = sf_addset(r, a); - } - return r; -} - -pcover make_disjoint(A) -pcover A; -{ - pcover R, new; - register pset last, p; - - R = new_cover(0); - foreach_set(A, last, p) { - new = cb_dsharp(p, R); - R = sf_append(R, new); - } - return R; -} - - -/* cv_dsharp -- disjoint-sharp product between two covers */ -pcover cv_dsharp(A, B) -pcover A, B; -{ - register pcube last, p; - pcover T; - - T = new_cover(0); - foreach_set(A, last, p) { - T = sf_union(T, cb_dsharp(p, B)); - } - return T; -} - - -/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */ -pcover cb1_dsharp(T, c) -pcover T; -pcube c; -{ - pcube last, p; - pcover R; - - R = new_cover(T->count); - foreach_set(T, last, p) { - R = sf_union(R, dsharp(p, c)); - } - return R; -} - - -/* cb_dsharp -- disjoint-sharp product between a cube and a cover */ -pcover cb_dsharp(c, T) -pcube c; -pcover T; -{ - pcube last, p; - pcover Y, Y1; - - if (T->count == 0) { - Y = sf_addset(new_cover(1), c); - } else { - Y = new_cover(T->count); - set_copy(GETSET(Y,Y->count++), c); - foreach_set(T, last, p) { - Y1 = cb1_dsharp(Y, p); - free_cover(Y); - Y = Y1; - } - } - return Y; -} - - -/* dsharp -- form the disjoint-sharp product between two cubes */ -pcover dsharp(a, b) -pcube a, b; -{ - register pcube mask, diff, and, temp, temp1 = cube.temp[0]; - int var; - pcover r; - - r = new_cover(cube.num_vars); - - if (cdist0(a, b)) { - diff = set_diff(new_cube(), a, b); - and = set_and(new_cube(), a, b); - mask = new_cube(); - for(var = 0; var < cube.num_vars; var++) { - /* check if position var of "a and not b" is not empty */ - if (! setp_disjoint(diff, cube.var_mask[var])) { - - /* coordinate var equals the difference between a and b */ - temp = GETSET(r, r->count++); - (void) set_and(temp, diff, cube.var_mask[var]); - - /* coordinates 0 ... var-1 equal the intersection */ - INLINEset_and(temp1, and, mask); - INLINEset_or(temp, temp, temp1); - - /* coordinates var+1 .. cube.num_vars equal a */ - set_or(mask, mask, cube.var_mask[var]); - INLINEset_diff(temp1, a, mask); - INLINEset_or(temp, temp, temp1); - } - } - free_cube(diff); - free_cube(and); - free_cube(mask); - } else { - r = sf_addset(r, a); - } - return r; -} - -/* cv_intersect -- form the intersection of two covers */ - -#define MAGIC 500 /* save 500 cubes before containment */ - -pcover cv_intersect(A, B) -pcover A, B; -{ - register pcube pi, pj, lasti, lastj, pt; - pcover T, Tsave = NULL; - - /* How large should each temporary result cover be ? */ - T = new_cover(MAGIC); - pt = T->data; - - /* Form pairwise intersection of each cube of A with each cube of B */ - foreach_set(A, lasti, pi) { - foreach_set(B, lastj, pj) { - if (cdist0(pi, pj)) { - (void) set_and(pt, pi, pj); - if (++T->count >= T->capacity) { - if (Tsave == NULL) - Tsave = sf_contain(T); - else - Tsave = sf_union(Tsave, sf_contain(T)); - T = new_cover(MAGIC); - pt = T->data; - } else - pt += T->wsize; - } - } - } - - - if (Tsave == NULL) - Tsave = sf_contain(T); - else - Tsave = sf_union(Tsave, sf_contain(T)); - return Tsave; -} diff --git a/src/benchmarks/espresso/sminterf.c b/src/benchmarks/espresso/sminterf.c deleted file mode 100644 index 96e77fa..0000000 --- a/src/benchmarks/espresso/sminterf.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "espresso.h" - - -pset -do_sm_minimum_cover(A) -pset_family A; -{ - sm_matrix *M; - sm_row *sparse_cover; - sm_element *pe; - pset cover; - register int i, base, rownum; - register unsigned val; - register pset last, p; - - M = sm_alloc(); - rownum = 0; - foreach_set(A, last, p) { - foreach_set_element(p, i, val, base) { - (void) sm_insert(M, rownum, base); - } - rownum++; - } - - sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0); - sm_free(M); - - cover = set_new(A->sf_size); - sm_foreach_row_element(sparse_cover, pe) { - set_insert(cover, pe->col_num); - } - sm_row_free(sparse_cover); - - return cover; -} diff --git a/src/benchmarks/espresso/solution.c b/src/benchmarks/espresso/solution.c deleted file mode 100644 index 2222b71..0000000 --- a/src/benchmarks/espresso/solution.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "espresso.h" -#include "mincov_int.h" - - -solution_t * -solution_alloc() -{ - solution_t *sol; - - sol = ALLOC(solution_t, 1); - sol->cost = 0; - sol->row = sm_row_alloc(); - return sol; -} - - -void -solution_free(sol) -solution_t *sol; -{ - sm_row_free(sol->row); - FREE(sol); -} - - -solution_t * -solution_dup(sol) -solution_t *sol; -{ - solution_t *new_sol; - - new_sol = ALLOC(solution_t, 1); - new_sol->cost = sol->cost; - new_sol->row = sm_row_dup(sol->row); - return new_sol; -} - - -void -solution_add(sol, weight, col) -solution_t *sol; -int *weight; -int col; -{ - (void) sm_row_insert(sol->row, col); - sol->cost += WEIGHT(weight, col); -} - - -void -solution_accept(sol, A, weight, col) -solution_t *sol; -sm_matrix *A; -int *weight; -int col; -{ - register sm_element *p, *pnext; - sm_col *pcol; - - solution_add(sol, weight, col); - - /* delete rows covered by this column */ - pcol = sm_get_col(A, col); - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; /* grab it before it disappears */ - sm_delrow(A, p->row_num); - } -} - - -/* ARGSUSED */ -void -solution_reject(sol, A, weight, col) -solution_t *sol; -sm_matrix *A; -int *weight; -int col; -{ - sm_delcol(A, col); -} - - -solution_t * -solution_choose_best(best1, best2) -solution_t *best1, *best2; -{ - if (best1 != NIL(solution_t)) { - if (best2 != NIL(solution_t)) { - if (best1->cost <= best2->cost) { - solution_free(best2); - return best1; - } else { - solution_free(best1); - return best2; - } - } else { - return best1; - } - } else { - if (best2 != NIL(solution_t)) { - return best2; - } else { - return NIL(solution_t); - } - } -} diff --git a/src/benchmarks/espresso/sparse.c b/src/benchmarks/espresso/sparse.c deleted file mode 100644 index 559b8ca..0000000 --- a/src/benchmarks/espresso/sparse.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - module: sparse.c - - make_sparse is a last-step cleanup to reduce the total number - of literals in the cover. - - This is done by reducing the "sparse" variables (using a modified - version of irredundant rather than reduce), followed by expanding - the "dense" variables (using modified version of expand). -*/ - -#include "espresso.h" - -pcover make_sparse(F, D, R) -pcover F, D, R; -{ - cost_t cost, best_cost; - - cover_cost(F, &best_cost); - - do { - EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost); - if (cost.total == best_cost.total) - break; - copy_cost(&cost, &best_cost); - - EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost); - if (cost.total == best_cost.total) - break; - copy_cost(&cost, &best_cost); - } while (force_irredundant); - - return F; -} - -/* - mv_reduce -- perform an "optimal" reduction of the variables which - we desire to be sparse - - This could be done using "reduce" and then saving just the desired - part of the reduction. Instead, this version uses IRRED to find - which cubes of an output are redundant. Note that this gets around - the cube-ordering problem. - - In normal use, it is expected that the cover is irredundant and - hence no cubes will be reduced to the empty cube (however, this is - checked for and such cubes will be deleted) -*/ - -pcover -mv_reduce(F, D) -pcover F, D; -{ - register int i, var; - register pcube p, p1, last; - int index; - pcover F1, D1; - pcube *F_cube_table; - - /* loop for each multiple-valued variable */ - for(var = 0; var < cube.num_vars; var++) { - - if (cube.sparse[var]) { - - /* loop for each part of the variable */ - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - - /* remember mapping of F1 cubes back to F cubes */ - F_cube_table = ALLOC(pcube, F->count); - - /* 'cofactor' against part #i of variable #var */ - F1 = new_cover(F->count); - foreach_set(F, last, p) { - if (is_in_set(p, i)) { - F_cube_table[F1->count] = p; - p1 = GETSET(F1, F1->count++); - (void) set_diff(p1, p, cube.var_mask[var]); - set_insert(p1, i); - } - } - - /* 'cofactor' against part #i of variable #var */ - /* not really necessary -- just more efficient ? */ - D1 = new_cover(D->count); - foreach_set(D, last, p) { - if (is_in_set(p, i)) { - p1 = GETSET(D1, D1->count++); - (void) set_diff(p1, p, cube.var_mask[var]); - set_insert(p1, i); - } - } - - mark_irredundant(F1, D1); - - /* now remove part i from cubes which are redundant */ - index = 0; - foreach_set(F1, last, p1) { - if (! TESTP(p1, ACTIVE)) { - p = F_cube_table[index]; - - /* don't reduce a variable which is full - * (unless it is the output variable) - */ - if (var == cube.num_vars-1 || - ! setp_implies(cube.var_mask[var], p)) { - set_remove(p, i); - } - RESET(p, PRIME); - } - index++; - } - - free_cover(F1); - free_cover(D1); - FREE(F_cube_table); - } - } - } - - /* Check if any cubes disappeared */ - (void) sf_active(F); - for(var = 0; var < cube.num_vars; var++) { - if (cube.sparse[var]) { - foreach_active_set(F, last, p) { - if (setp_disjoint(p, cube.var_mask[var])) { - RESET(p, ACTIVE); - F->active_count--; - } - } - } - } - - if (F->count != F->active_count) { - F = sf_inactive(F); - } - return F; -} diff --git a/src/benchmarks/espresso/sparse.h b/src/benchmarks/espresso/sparse.h deleted file mode 100644 index 9c84827..0000000 --- a/src/benchmarks/espresso/sparse.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef SPARSE_H -#define SPARSE_H - -/* - * sparse.h -- sparse matrix package header file - */ - -typedef struct sm_element_struct sm_element; -typedef struct sm_row_struct sm_row; -typedef struct sm_col_struct sm_col; -typedef struct sm_matrix_struct sm_matrix; - - -/* - * sparse matrix element - */ -struct sm_element_struct { - int row_num; /* row number of this element */ - int col_num; /* column number of this element */ - sm_element *next_row; /* next row in this column */ - sm_element *prev_row; /* previous row in this column */ - sm_element *next_col; /* next column in this row */ - sm_element *prev_col; /* previous column in this row */ - char *user_word; /* user-defined word */ -}; - - -/* - * row header - */ -struct sm_row_struct { - int row_num; /* the row number */ - int length; /* number of elements in this row */ - int flag; /* user-defined word */ - sm_element *first_col; /* first element in this row */ - sm_element *last_col; /* last element in this row */ - sm_row *next_row; /* next row (in sm_matrix linked list) */ - sm_row *prev_row; /* previous row (in sm_matrix linked list) */ - char *user_word; /* user-defined word */ -}; - - -/* - * column header - */ -struct sm_col_struct { - int col_num; /* the column number */ - int length; /* number of elements in this column */ - int flag; /* user-defined word */ - sm_element *first_row; /* first element in this column */ - sm_element *last_row; /* last element in this column */ - sm_col *next_col; /* next column (in sm_matrix linked list) */ - sm_col *prev_col; /* prev column (in sm_matrix linked list) */ - char *user_word; /* user-defined word */ -}; - - -/* - * A sparse matrix - */ -struct sm_matrix_struct { - sm_row **rows; /* pointer to row headers (by row #) */ - int rows_size; /* alloc'ed size of above array */ - sm_col **cols; /* pointer to column headers (by col #) */ - int cols_size; /* alloc'ed size of above array */ - sm_row *first_row; /* first row (linked list of all rows) */ - sm_row *last_row; /* last row (linked list of all rows) */ - int nrows; /* number of rows */ - sm_col *first_col; /* first column (linked list of columns) */ - sm_col *last_col; /* last column (linked list of columns) */ - int ncols; /* number of columns */ - char *user_word; /* user-defined word */ -}; - - -#define sm_get_col(A, colnum) \ - (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \ - (A)->cols[colnum] : (sm_col *) 0) - -#define sm_get_row(A, rownum) \ - (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \ - (A)->rows[rownum] : (sm_row *) 0) - -#define sm_foreach_row(A, prow) \ - for(prow = A->first_row; prow != 0; prow = prow->next_row) - -#define sm_foreach_col(A, pcol) \ - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) - -#define sm_foreach_row_element(prow, p) \ - for(p = prow->first_col; p != 0; p = p->next_col) - -#define sm_foreach_col_element(pcol, p) \ - for(p = pcol->first_row; p != 0; p = p->next_row) - -#define sm_put(x, val) \ - (x->user_word = (char *) val) - -#define sm_get(type, x) \ - ((type) (x->user_word)) - -extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup(); -extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize(); -extern void sm_write(), sm_print(), sm_dump(), sm_cleanup(); -extern void sm_copy_row(), sm_copy_col(); -extern void sm_remove(), sm_remove_element(); -extern sm_element *sm_insert(), *sm_find(); -extern sm_row *sm_longest_row(); -extern sm_col *sm_longest_col(); -extern int sm_read(), sm_read_compressed(); - -extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and(); -extern void sm_row_free(), sm_row_remove(), sm_row_print(); -extern sm_element *sm_row_insert(), *sm_row_find(); -extern int sm_row_contains(), sm_row_intersects(); -extern int sm_row_compare(), sm_row_hash(); - -extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and(); -extern void sm_col_free(), sm_col_remove(), sm_col_print(); -extern sm_element *sm_col_insert(), *sm_col_find(); -extern int sm_col_contains(), sm_col_intersects(); -extern int sm_col_compare(), sm_col_hash(); - -extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition(); - -#endif diff --git a/src/benchmarks/espresso/sparse_int.h b/src/benchmarks/espresso/sparse_int.h deleted file mode 100644 index d80cfed..0000000 --- a/src/benchmarks/espresso/sparse_int.h +++ /dev/null @@ -1,110 +0,0 @@ -#include "port.h" -#include "utility.h" -#include "sparse.h" - - - -/* - * sorted, double-linked list insertion - * - * type: object type - * - * first, last: fields (in header) to head and tail of the list - * count: field (in header) of length of the list - * - * next, prev: fields (in object) to link next and previous objects - * value: field (in object) which controls the order - * - * newval: value field for new object - * e: an object to use if insertion needed (set to actual value used) - */ - -#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \ - if (last == 0) { \ - e->value = newval; \ - first = e; \ - last = e; \ - e->next = 0; \ - e->prev = 0; \ - count++; \ - } else if (last->value < newval) { \ - e->value = newval; \ - last->next = e; \ - e->prev = last; \ - last = e; \ - e->next = 0; \ - count++; \ - } else if (first->value > newval) { \ - e->value = newval; \ - first->prev = e; \ - e->next = first; \ - first = e; \ - e->prev = 0; \ - count++; \ - } else { \ - type *p; \ - for(p = first; p->value < newval; p = p->next) \ - ; \ - if (p->value > newval) { \ - e->value = newval; \ - p = p->prev; \ - p->next->prev = e; \ - e->next = p->next; \ - p->next = e; \ - e->prev = p; \ - count++; \ - } else { \ - e = p; \ - } \ - } - - -/* - * double linked-list deletion - */ -#define dll_unlink(p, first, last, next, prev, count) { \ - if (p->prev == 0) { \ - first = p->next; \ - } else { \ - p->prev->next = p->next; \ - } \ - if (p->next == 0) { \ - last = p->prev; \ - } else { \ - p->next->prev = p->prev; \ - } \ - count--; \ -} - - -#ifdef FAST_AND_LOOSE -extern sm_element *sm_element_freelist; -extern sm_row *sm_row_freelist; -extern sm_col *sm_col_freelist; - -#define sm_element_alloc(newobj) \ - if (sm_element_freelist == NIL(sm_element)) { \ - newobj = ALLOC(sm_element, 1); \ - } else { \ - newobj = sm_element_freelist; \ - sm_element_freelist = sm_element_freelist->next_col; \ - } \ - newobj->user_word = NIL(char); \ - -#define sm_element_free(e) \ - (e->next_col = sm_element_freelist, sm_element_freelist = e) - -#else - -#define sm_element_alloc(newobj) \ - newobj = ALLOC(sm_element, 1); \ - newobj->user_word = NIL(char); -#define sm_element_free(e) \ - FREE(e) -#endif - - -extern void sm_row_remove_element(); -extern void sm_col_remove_element(); - -/* LINTLIBRARY */ diff --git a/src/benchmarks/espresso/stdlib.h b/src/benchmarks/espresso/stdlib.h deleted file mode 100644 index c5cf479..0000000 --- a/src/benchmarks/espresso/stdlib.h +++ /dev/null @@ -1,38 +0,0 @@ -/* ANSI Compatible stdlib.h stub */ - -#ifndef __cplusplus - -#include <sys/types.h> - -#ifndef ultrix4 -extern double atof(const char *); -extern int atoi(const char *); -extern long atol(const char *); -extern void abort(void); -extern void *calloc(size_t, size_t); -extern void exit(int); -extern void free(void *); -extern void *malloc(size_t); -extern void *realloc(void *, size_t); -extern char *getenv(const char *); -#else -extern double atof(const char *); -extern int atoi(char *); -extern long atol(char *); -extern void abort(void); -extern void *calloc(size_t, size_t); -extern void exit(int); -extern void free(void *); -extern void *malloc(size_t); -extern void *realloc(void *, size_t); -extern char *getenv(char *); -#endif - -/* should be in stdio.h */ -extern void perror(const char *); - -#ifdef LINT -#undef putc -#endif - -#endif diff --git a/src/benchmarks/espresso/unate.c b/src/benchmarks/espresso/unate.c deleted file mode 100644 index b787c3c..0000000 --- a/src/benchmarks/espresso/unate.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * unate.c -- routines for dealing with unate functions - */ - -#include "espresso.h" - -static pset_family abs_covered(); -static pset_family abs_covered_many(); -static int abs_select_restricted(); - -pcover map_cover_to_unate(T) -pcube *T; -{ - register unsigned int word_test, word_set, bit_test, bit_set; - register pcube p, pA; - pset_family A; - pcube *T1; - int ncol, i; - - A = sf_new(CUBELISTSIZE(T), cdata.vars_unate); - A->count = CUBELISTSIZE(T); - foreachi_set(A, i, p) { - (void) set_clear(p, A->sf_size); - } - ncol = 0; - - for(i = 0; i < cube.size; i++) { - if (cdata.part_zeros[i] > 0) { - assert(ncol <= cdata.vars_unate); - - /* Copy a column from T to A */ - word_test = WHICH_WORD(i); - bit_test = 1 << WHICH_BIT(i); - word_set = WHICH_WORD(ncol); - bit_set = 1 << WHICH_BIT(ncol); - - pA = A->data; - for(T1 = T+2; (p = *T1++) != 0; ) { - if ((p[word_test] & bit_test) == 0) { - pA[word_set] |= bit_set; - } - pA += A->wsize; - } - - ncol++; - } - } - - return A; -} - -pcover map_unate_to_cover(A) -pset_family A; -{ - register int i, ncol, lp; - register pcube p, pB; - int var, nunate, *unate; - pcube last; - pset_family B; - - B = sf_new(A->count, cube.size); - B->count = A->count; - - /* Find the unate variables */ - unate = ALLOC(int, cube.num_vars); - nunate = 0; - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - unate[nunate++] = var; - } - } - - /* Loop for each set of A */ - pB = B->data; - foreach_set(A, last, p) { - - /* Initialize this set of B */ - INLINEset_fill(pB, cube.size); - - /* Now loop for the unate variables; if the part is in A, - * then this variable of B should be a single 1 in the unate - * part. - */ - for(ncol = 0; ncol < nunate; ncol++) { - if (is_in_set(p, ncol)) { - lp = cube.last_part[unate[ncol]]; - for(i = cube.first_part[unate[ncol]]; i <= lp; i++) { - if (cdata.part_zeros[i] == 0) { - set_remove(pB, i); - } - } - } - } - pB += B->wsize; - } - - FREE(unate); - return B; -} - -/* - * unate_compl - */ - -pset_family unate_compl(A) -pset_family A; -{ - register pset p, last; - - /* Make sure A is single-cube containment minimal */ -/* A = sf_rev_contain(A);*/ - - foreach_set(A, last, p) { - PUTSIZE(p, set_ord(p)); - } - - /* Recursively find the complement */ - A = unate_complement(A); - - /* Now, we can guarantee a minimal result by containing the result */ - A = sf_rev_contain(A); - return A; -} - - -/* - * Assume SIZE(p) records the size of each set - */ -pset_family unate_complement(A) -pset_family A; /* disposes of A */ -{ - pset_family Abar; - register pset p, p1, restrictx; - register int i; - int max_i, min_set_ord, j; - - /* Check for no sets in the matrix -- complement is the universe */ - if (A->count == 0) { - sf_free(A); - Abar = sf_new(1, A->sf_size); - (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size); - - /* Check for a single set in the maxtrix -- compute de Morgan complement */ - } else if (A->count == 1) { - p = A->data; - Abar = sf_new(A->sf_size, A->sf_size); - for(i = 0; i < A->sf_size; i++) { - if (is_in_set(p, i)) { - p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size); - set_insert(p1, i); - } - } - sf_free(A); - - } else { - - /* Select splitting variable as the variable which belongs to a set - * of the smallest size, and which has greatest column count - */ - restrictx = set_new(A->sf_size); - min_set_ord = A->sf_size + 1; - foreachi_set(A, i, p) { - if (SIZE(p) < min_set_ord) { - set_copy(restrictx, p); - min_set_ord = SIZE(p); - } else if (SIZE(p) == min_set_ord) { - set_or(restrictx, restrictx, p); - } - } - - /* Check for no data (shouldn't happen ?) */ - if (min_set_ord == 0) { - A->count = 0; - Abar = A; - - /* Check for "essential" columns */ - } else if (min_set_ord == 1) { - Abar = unate_complement(abs_covered_many(A, restrictx)); - sf_free(A); - foreachi_set(Abar, i, p) { - set_or(p, p, restrictx); - } - - /* else, recur as usual */ - } else { - max_i = abs_select_restricted(A, restrictx); - - /* Select those rows of A which are not covered by max_i, - * recursively find all minimal covers of these rows, and - * then add back in max_i - */ - Abar = unate_complement(abs_covered(A, max_i)); - foreachi_set(Abar, i, p) { - set_insert(p, max_i); - } - - /* Now recur on A with all zero's on column max_i */ - foreachi_set(A, i, p) { - if (is_in_set(p, max_i)) { - set_remove(p, max_i); - j = SIZE(p) - 1; - PUTSIZE(p, j); - } - } - - Abar = sf_append(Abar, unate_complement(A)); - } - set_free(restrictx); - } - - return Abar; -} - -pset_family exact_minimum_cover(T) -IN pset_family T; -{ - register pset p, last, p1; - register int i, n; - int lev, lvl; - pset nlast; - pset_family temp; - long start = ptime(); - struct { - pset_family sf; - int level; - } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */ - - if (T->count <= 0) - return sf_new(1, T->sf_size); - for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ; - - /* A simple heuristic ordering */ - T = lex_sort(sf_save(T)); - - /* Push a full set on the stack to get things started */ - n = 1; - stack[0].sf = sf_new(1, T->sf_size); - stack[0].level = lev; - set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size); - - nlast = GETSET(T, T->count - 1); - foreach_set(T, last, p) { - - /* "unstack" the set into a family */ - temp = sf_new(set_ord(p), T->sf_size); - for(i = 0; i < T->sf_size; i++) - if (is_in_set(p, i)) { - p1 = set_fill(GETSET(temp, temp->count++), T->sf_size); - set_remove(p1, i); - } - stack[n].sf = temp; - stack[n++].level = lev; - - /* Pop the stack and perform (leveled) intersections */ - while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) { - temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE); - lvl = MIN(stack[n-1].level, stack[n-2].level) - 1; - if (debug & MINCOV && lvl < 10) { - printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n", - lvl, temp->count, stack[n-1].sf->count, - stack[n-2].sf->count, print_time(ptime() - start)); - (void) fflush(stdout); - } - sf_free(stack[n-2].sf); - sf_free(stack[n-1].sf); - stack[n-2].sf = temp; - stack[n-2].level = lvl; - n--; - } - } - - temp = stack[0].sf; - p1 = set_fill(set_new(T->sf_size), T->sf_size); - foreach_set(temp, last, p) - INLINEset_diff(p, p1, p); - set_free(p1); - if (debug & MINCOV1) { - printf("MINCOV: family of all minimal coverings is\n"); - sf_print(temp); - } - sf_free(T); /* this is the copy of T we made ... */ - return temp; -} - -/* - * unate_intersect -- intersect two unate covers - * - * If largest_only is TRUE, then only the largest cube(s) are returned - */ - -#define MAGIC 500 /* save 500 cubes before containment */ - -pset_family unate_intersect(A, B, largest_only) -pset_family A, B; -bool largest_only; -{ - register pset pi, pj, lasti, lastj, pt; - pset_family T, Tsave; - bool save; - int maxord, ord; - - /* How large should each temporary result cover be ? */ - T = sf_new(MAGIC, A->sf_size); - Tsave = NULL; - maxord = 0; - pt = T->data; - - /* Form pairwise intersection of each set of A with each cube of B */ - foreach_set(A, lasti, pi) { - - foreach_set(B, lastj, pj) { - - save = set_andp(pt, pi, pj); - - /* Check if we want the largest only */ - if (save && largest_only) { - if ((ord = set_ord(pt)) > maxord) { - /* discard Tsave and T */ - if (Tsave != NULL) { - sf_free(Tsave); - Tsave = NULL; - } - pt = T->data; - T->count = 0; - /* Re-create pt (which was just thrown away) */ - (void) set_and(pt, pi, pj); - maxord = ord; - } else if (ord < maxord) { - save = FALSE; - } - } - - if (save) { - if (++T->count >= T->capacity) { - T = sf_contain(T); - Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); - T = sf_new(MAGIC, A->sf_size); - pt = T->data; - } else { - pt += T->wsize; - } - } - } - } - - - /* Contain the final result and merge it into Tsave */ - T = sf_contain(T); - Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); - - return Tsave; -} - -/* - * abs_covered -- after selecting a new column for the selected set, - * create a new matrix which is only those rows which are still uncovered - */ -static pset_family -abs_covered(A, pick) -pset_family A; -register int pick; -{ - register pset last, p, pdest; - register pset_family Aprime; - - Aprime = sf_new(A->count, A->sf_size); - pdest = Aprime->data; - foreach_set(A, last, p) - if (! is_in_set(p, pick)) { - INLINEset_copy(pdest, p); - Aprime->count++; - pdest += Aprime->wsize; - } - return Aprime; -} - - -/* - * abs_covered_many -- after selecting many columns for ther selected set, - * create a new matrix which is only those rows which are still uncovered - */ -static pset_family -abs_covered_many(A, pick_set) -pset_family A; -register pset pick_set; -{ - register pset last, p, pdest; - register pset_family Aprime; - - Aprime = sf_new(A->count, A->sf_size); - pdest = Aprime->data; - foreach_set(A, last, p) - if (setp_disjoint(p, pick_set)) { - INLINEset_copy(pdest, p); - Aprime->count++; - pdest += Aprime->wsize; - } - return Aprime; -} - - -/* - * abs_select_restricted -- select the column of maximum column count which - * also belongs to the set "restrictx"; weight each column of a set as - * 1 / (set_ord(p) - 1). - */ -static int -abs_select_restricted(A, restrictx) -pset_family A; -pset restrictx; -{ - register int i, best_var, best_count, *count; - - /* Sum the elements in these columns */ - count = sf_count_restricted(A, restrictx); - - /* Find which variable has maximum weight */ - best_var = -1; - best_count = 0; - for(i = 0; i < A->sf_size; i++) { - if (count[i] > best_count) { - best_var = i; - best_count = count[i]; - } - } - FREE(count); - - if (best_var == -1) - fatal("abs_select_restricted: should not have best_var == -1"); - - return best_var; -} diff --git a/src/benchmarks/espresso/utility.c b/src/benchmarks/espresso/utility.c deleted file mode 100644 index 3c140a1..0000000 --- a/src/benchmarks/espresso/utility.c +++ /dev/null @@ -1,162 +0,0 @@ -/* LINTLIBRARY */ -#include "espresso.h" -#include "copyright.h" -#include "port.h" -#include "utility.h" - -#ifdef IBM_WATC /* IBM Waterloo-C compiler (same as bsd 4.2) */ -#ifndef BSD -#define BSD -#endif -#ifndef void -#define void int -#endif -#endif - -#ifdef ultrix -#ifndef BSD -#define BSD -#endif -#endif - -#ifdef hpux -#ifndef UNIX50 -#define UNIX50 -#endif -#endif - -#ifdef aiws -#ifndef UNIX10 -#define UNIX10 -#endif -#endif - -#ifdef vms /* VAX/C compiler -- times() with 100 HZ clock */ -#ifndef UNIX100 -#define UNIX100 -#endif -#endif - -/* default */ -#if !defined(BSD) && !defined(UNIX10) && !defined(UNIX60) && !defined(UNIX100) && !defined(UNIX50) && !defined(_WIN32) -#define UNIX10 -#endif - -#ifdef BSD -#include <sys/time.h> -#include <sys/rusage.h> -#endif - -#ifdef UNIX10 -#include <sys/times.h> -#endif - -#ifdef UNIX50 -#include <sys/times.h> -#endif - -#ifdef UNIX60 -#include <sys/times.h> -#endif - -#ifdef UNIX100 -#include <sys/times.h> -#endif - -#ifdef _MSC_VER -#include <windows.h> -#include <stdint.h> -#endif - -/* - * util_cpu_time -- return a long which represents the elapsed processor - * time in milliseconds since some constant reference - */ -long -util_cpu_time() -{ - long t = 0; - -#ifdef _MSC_VER - static uint64_t frec = 0; - if (frec == 0) - { - LARGE_INTEGER val; - BOOL ok = QueryPerformanceFrequency(&val); - assert(ok); - frec = val.QuadPart / 1000; - } - LARGE_INTEGER val; - BOOL ok = QueryPerformanceCounter(&val); - assert(ok); - t = val.QuadPart / frec; -#endif - -#ifdef BSD - struct rusage rusage; - (void) getrusage(RUSAGE_SELF, &rusage); - t = (long) rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000; -#endif - -#ifdef IBMPC - long ltime; - (void) time(<ime); - t = ltime * 1000; -#endif - -#ifdef UNIX10 /* times() with 10 Hz resolution */ - struct tms buffer; - (void) times(&buffer); - t = buffer.tms_utime * 100; -#endif - -#ifdef UNIX50 /* times() with 50 Hz resolution */ - struct tms buffer; - times(&buffer); - t = buffer.tms_utime * 20; -#endif - -#ifdef UNIX60 /* times() with 60 Hz resolution */ - struct tms buffer; - times(&buffer); - t = buffer.tms_utime * 16.6667; -#endif - -#ifdef UNIX100 - struct tms buffer; /* times() with 100 Hz resolution */ - times(&buffer); - t = buffer.tms_utime * 10; -#endif - - return t; -} - - -/* - * util_print_time -- massage a long which represents a time interval in - * milliseconds, into a string suitable for output - * - * Hack for IBM/PC -- avoids using floating point - */ - -char * -util_print_time(t) -long t; -{ - static char s[40]; - - //(void) sprintf(s, "%ld.%02ld sec", 0/1000, (0%1000)/10); - (void) sprintf(s, "%ld.%03ld sec", t/1000, (t%1000)); - return s; -} - - -/* - * util_strsav -- save a copy of a string - */ -char * -util_strsav(s) -char *s; -{ - return strcpy(ALLOC(char, strlen(s)+1), s); -} diff --git a/src/benchmarks/espresso/utility.h b/src/benchmarks/espresso/utility.h deleted file mode 100644 index dcb834e..0000000 --- a/src/benchmarks/espresso/utility.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef UTILITY_H -#define UTILITY_H - -#include <stdlib.h> -#include <string.h> -//#include <stdbool.h> - -/* - * assumes the memory manager is libmm.a - * - allows malloc(0) or realloc(obj, 0) - * - catches out of memory (and calls MMout_of_memory()) - * - catch free(0) and realloc(0, size) in the macros - */ -#define NIL(type) ((type *) 0) - -#ifdef BWGC -#define ALLOC(type, num) \ - ((type *) gc_malloc(sizeof(type) * ((num)==0?1:(num)))) -#define REALLOC(type, obj, num) \ - (obj) ? ((type *) gc_realloc((char *) obj, sizeof(type) * ((num)==0?1:(num)))) : \ - ((type *) gc_malloc(sizeof(type) * ((num)==0?1:(num)))) -#elif defined(CUSTOM_MALLOC) -#define ALLOC(type, num) \ - ((type *) CUSTOM_MALLOC(sizeof(type) * (num))) -#define REALLOC(type, obj, num) \ - (obj) ? ((type *) CUSTOM_REALLOC((char *) obj, sizeof(type) * (num))) : \ - ((type *) CUSTOM_MALLOC(sizeof(type) * (num))) -#else -#include <stdlib.h> -#define ALLOC(type, num) \ - ((type *) malloc(sizeof(type) * (num))) -#define REALLOC(type, obj, num) \ - (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifdef IGNOREFREE -#define FREE(obj) \ - {}; -#elif defined(CUSTOM_FREE) -#define FREE(obj) \ - if ((obj)) { (void) CUSTOM_FREE((char *) (obj)); (obj) = 0; } -#else -#define FREE(obj) \ - if ((obj)) { (void) free((char *) (obj)); (obj) = 0; } -#endif - -#include "ansi.h" - -EXTERN long util_cpu_time - NULLARGS; -EXTERN char *util_path_search - ARGS((char *program)); -EXTERN char *util_file_search - ARGS((char *file, char *path, char *mode)); -EXTERN int util_pipefork - ARGS((char **argv, FILE **toCommand, FILE **fromCommand, int *pid)); -EXTERN int util_csystem - ARGS((char *command)); -EXTERN char *util_print_time - ARGS((long t)); -EXTERN char *util_strsav - ARGS((char *ptr)); -EXTERN char *util_tilde_expand - ARGS((char *filename)); -EXTERN char *util_tilde_compress - ARGS((char *filename)); -EXTERN void util_register_user - ARGS((char *user, char *directory)); - -#ifndef NIL_FN -#define NIL_FN(type) ((type (*)()) 0) -#endif /* NIL_FN */ - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif /* MAX */ -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif /* MIN */ -#ifndef ABS -#define ABS(a) ((a) > 0 ? (a) : -(a)) -#endif /* ABS */ - - -#ifdef lint -#undef ALLOC /* allow for lint -h flag */ -#undef REALLOC -#define ALLOC(type, num) (((type *) 0) + (num)) -#define REALLOC(type, obj, num) ((obj) + (num)) -#endif /* lint */ - -#endif diff --git a/src/benchmarks/espresso/verify.c b/src/benchmarks/espresso/verify.c deleted file mode 100644 index 3cecd8b..0000000 --- a/src/benchmarks/espresso/verify.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - */ - -#include "espresso.h" - -/* - * verify -- check that all minterms of F are contained in (Fold u Dold) - * and that all minterms of Fold are contained in (F u Dold). - */ -bool verify(F, Fold, Dold) -pcover F, Fold, Dold; -{ - pcube p, last, *FD; - bool verify_error = FALSE; - - /* Make sure the function didn't grow too large */ - FD = cube2list(Fold, Dold); - foreach_set(F, last, p) - if (! cube_is_covered(FD, p)) { - printf("some minterm in F is not covered by Fold u Dold\n"); - verify_error = TRUE; - if (verbose_debug) printf("%s\n", pc1(p)); else break; - } - free_cubelist(FD); - - /* Make sure minimized function covers the original function */ - FD = cube2list(F, Dold); - foreach_set(Fold, last, p) - if (! cube_is_covered(FD, p)) { - printf("some minterm in Fold is not covered by F u Dold\n"); - verify_error = TRUE; - if (verbose_debug) printf("%s\n", pc1(p)); else break; - } - free_cubelist(FD); - - return verify_error; -} - - - -/* - * PLA_verify -- verify that two PLA's are identical - * - * If names are given, row and column permutations are done to make - * the comparison meaningful. - * - */ -bool PLA_verify(PLA1, PLA2) -pPLA PLA1, PLA2; -{ - /* Check if both have names given; if so, attempt to permute to - * match the names - */ - if (PLA1->label != NULL && PLA1->label[0] != NULL && - PLA2->label != NULL && PLA2->label[0] != NULL) { - PLA_permute(PLA1, PLA2); - } else { - fprintf(stderr, "Warning: cannot permute columns without names\n"); - return TRUE; - } - - if (PLA1->F->sf_size != PLA2->F->sf_size) { - fprintf(stderr, "PLA_verify: PLA's are not the same size\n"); - return TRUE; - } - - return verify(PLA2->F, PLA1->F, PLA1->D); -} - - - -/* - * Permute the columns of PLA1 so that they match the order of PLA2 - * Discard any columns of PLA1 which are not in PLA2 - * Association is strictly by the names of the columns of the cover. - */ -PLA_permute(PLA1, PLA2) -pPLA PLA1, PLA2; -{ - register int i, j, *permute, npermute; - register char *labi; - char **label; - - /* determine which columns of PLA1 to save, and place these in the list - * "permute"; the order in this list is the final output order - */ - npermute = 0; - permute = ALLOC(int, PLA2->F->sf_size); - for(i = 0; i < PLA2->F->sf_size; i++) { - labi = PLA2->label[i]; - for(j = 0; j < PLA1->F->sf_size; j++) { - if (strcmp(labi, PLA1->label[j]) == 0) { - permute[npermute++] = j; - break; - } - } - } - - /* permute columns */ - if (PLA1->F != NULL) { - PLA1->F = sf_permute(PLA1->F, permute, npermute); - } - if (PLA1->R != NULL) { - PLA1->R = sf_permute(PLA1->R, permute, npermute); - } - if (PLA1->D != NULL) { - PLA1->D = sf_permute(PLA1->D, permute, npermute); - } - - /* permute the labels */ - label = ALLOC(char *, cube.size); - for(i = 0; i < npermute; i++) { - label[i] = PLA1->label[permute[i]]; - } - for(i = npermute; i < cube.size; i++) { - label[i] = NULL; - } - FREE(PLA1->label); - PLA1->label = label; - - FREE(permute); -} - - - -/* - * check_consistency -- test that the ON-set, OFF-set and DC-set form - * a partition of the boolean space. - */ -bool check_consistency(PLA) -pPLA PLA; -{ - bool verify_error = FALSE; - pcover T; - - T = cv_intersect(PLA->F, PLA->D); - if (T->count == 0) - printf("ON-SET and DC-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - T = cv_intersect(PLA->F, PLA->R); - if (T->count == 0) - printf("ON-SET and OFF-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - T = cv_intersect(PLA->D, PLA->R); - if (T->count == 0) - printf("DC-SET and OFF-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - if (tautology(cube3list(PLA->F, PLA->D, PLA->R))) - printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n"); - else { - T = complement(cube3list(PLA->F, PLA->D, PLA->R)); - printf("There are minterms left unspecified !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - free_cover(T); - } - (void) fflush(stdout); - return verify_error; -} diff --git a/src/benchmarks/falsesharing.py b/src/benchmarks/falsesharing.py deleted file mode 100644 index 1e9fc34..0000000 --- a/src/benchmarks/falsesharing.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the falsesahring benchmark""" - -import re - -import matplotlib.pyplot as plt -import numpy as np - -from src.benchmark import Benchmark -from src.globalvars import summary_file_ext -import src.plots as plt - -TIME_RE = re.compile("^Time elapsed = (?P<time>\\d*\\.\\d*) seconds.$") - - -class BenchmarkFalsesharing(Benchmark): - """Falsesharing benchmark. - - This benchmarks makes small allocations and writes to them multiple - times. If the allocated objects are on the same cache line the writes - will be expensive because of cache thrashing. - """ - def __init__(self): - name = "falsesharing" - - self.cmd = "cache-{bench}{binary_suffix} {threads} 100 8 10000000" - - self.args = { - "bench": ["thrash", "scratch"], - "threads": Benchmark.scale_threads_for_cpus(1) - } - - self.requirements = ["cache-thrash", "cache-scratch"] - super().__init__(name) - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - result["time"] = TIME_RE.match(stdout).group("time") - - def summary(self): - args = self.results["args"] - nthreads = args["threads"] - allocators = self.results["allocators"] - - # calculate relevant datapoints: speedup, l1-cache-misses - for bench in self.results["args"]["bench"]: - for allocator in allocators: - - sequential_perm = self.Perm(bench=bench, threads=1) - for perm in self.iterate_args({"bench": bench}, args=args): - speedup = [] - l1chache_misses = [] - for i, measure in enumerate(self.results[allocator][perm]): - sequential_time = float(self.results[allocator] - [sequential_perm][i]["time"]) - measure["speedup"] = sequential_time / float( - measure["time"]) - measure["l1chache_misses"] = eval( - "({L1-dcache-load-misses}/{L1-dcache-loads})*100". - format(**measure)) - - # delete and recalculate stats - del self.results["stats"] - self.calc_desc_statistics() - - plt.plot(self, - "{speedup}", - x_args=["bench"], - fig_options={ - 'ylabel': "Speedup", - 'title': "Speedup: {arg} {arg_value}", - 'autoticks': False, - }, - file_postfix="speedup") - - plt.plot(self, - "{l1chache_misses}", - x_args=["bench"], - fig_options={ - 'ylabel': "l1 cache misses in %", - 'title': "cache misses: {arg} {arg_value}", - 'autoticks': False, - }, - file_postfix="l1-misses") - - plt.write_tex_table(self, [{ - "label": "Speedup", - "expression": "{speedup}", - "sort": ">" - }], - file_postfix="speedup.table") - - # plt.export_stats_to_csv(self, "speedup", "time") - # plt.export_stats_to_csv(self, "l1chache_misses", "l1-misses") - - # pgfplots - for bench in args["bench"]: - plt.pgfplot(self, - self.iterate_args({"bench": bench}, args=args), - "int(perm.threads)", - "{speedup}", - xlabel="Threads", - ylabel="Speedup", - title=f"{bench}: Speedup", - postfix=f"{bench}.speedup") - - # create pgfplot legend - plt.pgfplot_legend(self) - - -falsesharing = BenchmarkFalsesharing() diff --git a/src/benchmarks/falsesharing/Makefile b/src/benchmarks/falsesharing/Makefile deleted file mode 100644 index 2058b05..0000000 --- a/src/benchmarks/falsesharing/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -OBJDIR ?= obj - -CXX ?= g++ - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -g -OPTFLAGS ?= -O0 - -CXXFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDXXFLAGS ?= -pthread -static-libgcc -static-libstdc++ - -HEADER = cpuinfo.h fred.h timer.h - -.PHONY = all clean - -all: $(OBJDIR)/cache-thrash $(OBJDIR)/cache-scratch - -$(OBJDIR)/cache-thrash: cache-thrash.cc $(HEADER) | $(OBJDIR) - @echo compiling $@... - $(CXX) $(LDXXFLAGS) $(CXXFLAGS) -o $@ $< - -$(OBJDIR)/cache-scratch: cache-scratch.cc $(HEADER) | $(OBJDIR) - @echo compiling $@... - $(CXX) $(LDXXFLAGS) $(CXXFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/falsesharing/cache-scratch.cc b/src/benchmarks/falsesharing/cache-scratch.cc deleted file mode 100644 index 2cb9b28..0000000 --- a/src/benchmarks/falsesharing/cache-scratch.cc +++ /dev/null @@ -1,147 +0,0 @@ -///-*-C++-*-////////////////////////////////////////////////////////////////// -// -// Hoard: A Fast, Scalable, and Memory-Efficient Allocator -// for Shared-Memory Multiprocessors -// Contact author: Emery Berger, http://www.cs.umass.edu/~emery -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License as -// published by the Free Software Foundation, http://www.fsf.org. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Library General Public License for more details. -// -////////////////////////////////////////////////////////////////////////////// - -/** - * @file cache-scratch.cpp - * - * cache-scratch is a benchmark that exercises a heap's cache locality. - * An allocator that allows multiple threads to re-use the same small - * object (possibly all in one cache-line) will scale poorly, while - * an allocator like Hoard will exhibit near-linear scaling. - * - * Try the following (on a P-processor machine): - * - * cache-scratch 1 1000 1 1000000 - * cache-scratch P 1000 1 1000000 - * - * cache-scratch-hoard 1 1000 1 1000000 - * cache-scratch-hoard P 1000 1 1000000 - * - * The ideal is a P-fold speedup. -*/ - -#include <stdio.h> -#include <stdlib.h> - -#include "fred.h" -#include "cpuinfo.h" -#include "timer.h" - -// This class just holds arguments to each thread. -class workerArg { -public: - - workerArg() {} - - workerArg (char * obj, int objSize, int repetitions, int iterations) - : _object (obj), - _objSize (objSize), - _iterations (iterations), - _repetitions (repetitions) - {} - - char * _object; - int _objSize; - int _iterations; - int _repetitions; -}; - - -#if defined(_WIN32) -extern "C" void worker (void * arg) -#else -extern "C" void * worker (void * arg) -#endif -{ - // free the object we were given. - // Then, repeatedly do the following: - // malloc a given-sized object, - // repeatedly write on it, - // then free it. - workerArg * w = (workerArg *) arg; - delete w->_object; - workerArg w1 = *w; - for (int i = 0; i < w1._iterations; i++) { - // Allocate the object. - char * obj = new char[w1._objSize]; - // Write into it a bunch of times. - for (int j = 0; j < w1._repetitions; j++) { - for (int k = 0; k < w1._objSize; k++) { - obj[k] = (char) k; - volatile char ch = obj[k]; - ch++; - } - } - // Free the object. - delete [] obj; - } - -#if !defined(_WIN32) - return NULL; -#endif -} - - -int main (int argc, char * argv[]) -{ - int nthreads; - int iterations; - int objSize; - int repetitions; - - if (argc > 4) { - nthreads = atoi(argv[1]); - iterations = atoi(argv[2]); - objSize = atoi(argv[3]); - repetitions = atoi(argv[4]); - } else { - fprintf (stderr, "Usage: %s nthreads iterations objSize repetitions\n", argv[0]); - return 1; - } - - HL::Fred * threads = new HL::Fred[nthreads]; - HL::Fred::setConcurrency (HL::CPUInfo::getNumProcessors()); - - workerArg * w = new workerArg[nthreads]; - - int i; - - // Allocate nthreads objects and distribute them among the threads. - char ** objs = new char * [nthreads]; - for (i = 0; i < nthreads; i++) { - objs[i] = new char[objSize]; - } - - HL::Timer t; - t.start(); - - for (i = 0; i < nthreads; i++) { - w[i] = workerArg (objs[i], objSize, repetitions / nthreads, iterations); - threads[i].create (&worker, (void *) &w[i]); - } - for (i = 0; i < nthreads; i++) { - threads[i].join(); - } - t.stop(); - - delete [] threads; - delete [] objs; - delete [] w; - - printf ("Time elapsed = %f seconds.\n", (double) t); - return 0; -} diff --git a/src/benchmarks/falsesharing/cache-thrash.cc b/src/benchmarks/falsesharing/cache-thrash.cc deleted file mode 100644 index 79242eb..0000000 --- a/src/benchmarks/falsesharing/cache-thrash.cc +++ /dev/null @@ -1,134 +0,0 @@ -///-*-C++-*-////////////////////////////////////////////////////////////////// -// -// Hoard: A Fast, Scalable, and Memory-Efficient Allocator -// for Shared-Memory Multiprocessors -// Contact author: Emery Berger, http://www.cs.umass.edu/~emery -// -// Copyright (c) 1998-2003, The University of Texas at Austin. -// -// This library is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License as -// published by the Free Software Foundation, http://www.fsf.org. -// -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Library General Public License for more details. -// -////////////////////////////////////////////////////////////////////////////// - -/** - * @file cache-thrash.cpp - * @brief cache-thrash is a benchmark that exercises a heap's cache-locality. - * - * Try the following (on a P-processor machine): - * - * cache-thrash 1 1000 1 1000000 - * cache-thrash P 1000 1 1000000 - * - * cache-thrash-hoard 1 1000 1 1000000 - * cache-thrash-hoard P 1000 1 1000000 - * - * The ideal is a P-fold speedup. -*/ - - -#include <iostream> -#include <stdlib.h> - -using namespace std; - -#include "cpuinfo.h" -#include "fred.h" -#include "timer.h" - -// This class just holds arguments to each thread. -class workerArg { -public: - workerArg() {} - workerArg (int objSize, int repetitions, int iterations) - : _objSize (objSize), - _iterations (iterations), - _repetitions (repetitions) - {} - - int _objSize; - int _iterations; - int _repetitions; -}; - - -#if defined(_WIN32) -extern "C" void worker (void * arg) -#else -extern "C" void * worker (void * arg) -#endif -{ - // Repeatedly do the following: - // malloc a given-sized object, - // repeatedly write on it, - // then free it. - workerArg * w = (workerArg *) arg; - workerArg w1 = *w; - for (int i = 0; i < w1._iterations; i++) { - // Allocate the object. - char * obj = new char[w1._objSize]; - // printf ("obj = %p\n", obj); - // Write into it a bunch of times. - for (int j = 0; j < w1._repetitions; j++) { - for (int k = 0; k < w1._objSize; k++) { - obj[k] = (char) k; - volatile char ch = obj[k]; - ch++; - } - } - // Free the object. - delete [] obj; - } -#if !defined(_WIN32) - return NULL; -#endif -} - - -int main (int argc, char * argv[]) -{ - int nthreads; - int iterations; - int objSize; - int repetitions; - - if (argc > 4) { - nthreads = atoi(argv[1]); - iterations = atoi(argv[2]); - objSize = atoi(argv[3]); - repetitions = atoi(argv[4]); - } else { - cerr << "Usage: " << argv[0] << " nthreads iterations objSize repetitions" << endl; - exit(1); - } - - HL::Fred * threads = new HL::Fred[nthreads]; - HL::Fred::setConcurrency (HL::CPUInfo::getNumProcessors()); - - int i; - - HL::Timer t; - t.start(); - - workerArg * w = new workerArg[nthreads]; - - for (i = 0; i < nthreads; i++) { - w[i] = workerArg (objSize, repetitions / nthreads, iterations); - threads[i].create (&worker, (void *) &w[i]); - } - for (i = 0; i < nthreads; i++) { - threads[i].join(); - } - t.stop(); - - delete [] threads; - delete [] w; - - cout << "Time elapsed = " << (double) t << " seconds." << endl; -} diff --git a/src/benchmarks/falsesharing/cpuinfo.h b/src/benchmarks/falsesharing/cpuinfo.h deleted file mode 100644 index 1ed1f36..0000000 --- a/src/benchmarks/falsesharing/cpuinfo.h +++ /dev/null @@ -1,202 +0,0 @@ -// -*- C++ -*-
-
-/*
-
- Heap Layers: An Extensible Memory Allocation Infrastructure
-
- Copyright (C) 2000-2003 by Emery Berger
- http://www.cs.umass.edu/~emery
- emery@cs.umass.edu
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-
-
-#ifndef HL_CPUINFO_H
-#define HL_CPUINFO_H
-
-#if defined(_WIN32)
-#include <windows.h>
-#include <process.h>
-#else
-#include <unistd.h>
-#endif
-
-
-#if !defined(_WIN32)
-#include <pthread.h>
-#endif
-
-#if defined(__SVR4) // Solaris
-#include <sys/lwp.h>
-extern "C" unsigned int lwp_self(void);
-#include <thread.h>
-extern "C" int _thr_self(void);
-#endif
-
-#if defined(__linux)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#endif
-
-#if defined(__APPLE__)
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#endif
-
-#if defined(__sgi)
-#include <sys/types.h>
-#include <sys/sysmp.h>
-#include <sys/sysinfo.h>
-#endif
-
-#if defined(hpux)
-#include <sys/mpctl.h>
-#endif
-
-#if defined(_WIN32)
-extern __declspec(thread) int localThreadId;
-#endif
-
-#if defined(__SVR4) && defined(MAP_ALIGN)
-extern volatile int anyThreadStackCreated;
-#endif
-
-namespace HL {
-
-/**
- * @class CPUInfo
- * @author Emery Berger <http://www.cs.umass.edu/~emery>
- *
- * @brief Architecture-independent wrapper to get number of CPUs.
- */
-
-class CPUInfo {
-public:
- CPUInfo (void)
- {}
-
- inline static int getNumProcessors (void) {
- static int _numProcessors = computeNumProcessors();
- return _numProcessors;
- }
-
- static inline unsigned long getThreadId (void);
- inline static int computeNumProcessors (void);
-
-};
-
-
-int CPUInfo::computeNumProcessors (void)
-{
- static int np = 0;
- if (!np) {
-#if defined(__linux) || defined(__APPLE__)
- np = (int) sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(_WIN32)
- SYSTEM_INFO infoReturn[1];
- GetSystemInfo (infoReturn);
- np = (int) (infoReturn->dwNumberOfProcessors);
-#elif defined(__sgi)
- np = (int) sysmp(MP_NAPROCS);
-#elif defined(hpux)
- np = mpctl(MPC_GETNUMSPUS, NULL, NULL); // or pthread_num_processors_np()?
-#elif defined(_SC_NPROCESSORS_ONLN)
- np = (int) (sysconf(_SC_NPROCESSORS_ONLN));
-#else
- np = 2;
- // Unsupported platform.
- // Pretend we have at least two processors. This approach avoids the risk of assuming
- // we're on a uniprocessor, which might lead clever allocators to avoid using atomic
- // operations for all locks.
-#endif
- return np;
- } else {
- return np;
- }
-}
-
- // Note: when stacksize arg is NULL for pthread_attr_setstacksize [Solaris],
-// stack size is 1 MB for 32-bit arch, 2 MB for 64-bit arch.
-// pthread_attr_getstacksize
-// pthread_attr_setstackaddr
-// pthread_attr_getstackaddr
-// PTHREAD_STACK_SIZE is minimum.
-// or should we just assume we have __declspec(thread) or __thread?
-
-#if defined(USE_THREAD_KEYWORD)
- extern __thread int localThreadId;
-#endif
-
- // FIX ME FIXME
- //#include <stdio.h>
-
-unsigned long CPUInfo::getThreadId (void) {
-#if defined(__SVR4)
- size_t THREAD_STACK_SIZE;
- if (sizeof(size_t) <= 4) {
- THREAD_STACK_SIZE = 1048576;
- } else {
- // 64-bits.
- THREAD_STACK_SIZE = 1048576 * 2;
- }
- if (0) { // !anyThreadStackCreated) {
- // We know a priori that all stack variables
- // are on different stacks. Since no one has created
- // a special one, we are in control, and thus all stacks
- // are 1 MB in size and on 1 MB boundaries.
- // (Actually: 1 MB for 32-bits, 2 MB for 64-bits.)
- char buf;
- return (((size_t) &buf) & ~(THREAD_STACK_SIZE-1)) >> 20;
- } else {
- return (int) pthread_self();
- }
-#elif defined(_WIN32)
- // It looks like thread id's are always multiples of 4, so...
- return GetCurrentThreadId() >> 2;
-#elif defined(__APPLE__)
- // Consecutive thread id's in Mac OS are 4096 apart;
- // dividing off the 4096 gives us an appropriate thread id.
- int tid = (int) ((unsigned long) pthread_self()) >> 12;
- return tid;
-#elif defined(__BEOS__)
- return find_thread(0);
-#elif defined(USE_THREAD_KEYWORD)
- return localThreadId;
-#elif defined(__linux) || defined(PTHREAD_KEYS_MAX)
- // Consecutive thread id's in Linux are 1024 apart;
- // dividing off the 1024 gives us an appropriate thread id.
- return (unsigned long) pthread_self() >> 10;
-#elif defined(POSIX)
- return (unsigned long) pthread_self();
-#elif USE_SPROC
- // This hairiness has the same effect as calling getpid(),
- // but it's MUCH faster since it avoids making a system call
- // and just accesses the sproc-local data directly.
- unsigned long pid = (unsigned long) PRDA->sys_prda.prda_sys.t_pid;
- return pid;
-#else
- return 0;
-#endif
-}
-
-}
-
-#endif
diff --git a/src/benchmarks/falsesharing/fred.h b/src/benchmarks/falsesharing/fred.h deleted file mode 100644 index b0198a7..0000000 --- a/src/benchmarks/falsesharing/fred.h +++ /dev/null @@ -1,97 +0,0 @@ -// -*- C++ -*- - -#ifndef HL_FRED_H -#define HL_FRED_H - -/// A thread-wrapper of childlike simplicity :). - -#if defined(_WIN32) - - #include <windows.h> - #include <process.h> - -#elif defined(__SVR4) - - #include <thread.h> - #include <pthread.h> - #include <unistd.h> - -#else - - #include <pthread.h> - #include <unistd.h> - -#endif - -typedef void * (*ThreadFunctionType) (void *); - -namespace HL { - -class Fred { -public: - - Fred() { -#if !defined(_WIN32) - pthread_attr_init (&attr); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); -#endif - } - - ~Fred() { -#if !defined(_WIN32) - pthread_attr_destroy (&attr); -#endif - } - - void create (ThreadFunctionType function, void * arg) { -#if defined(_WIN32) - t = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) *function, (LPVOID) arg, 0, 0); -#else - pthread_create (&t, &attr, function, arg); -#endif - } - - void join (void) { -#if defined(_WIN32) - WaitForSingleObject (t, INFINITE); -#else - pthread_join (t, NULL); -#endif - } - - static void yield (void) { -#if defined(_WIN32) - Sleep (0); -#elif defined(__SVR4) - thr_yield(); -#else - sched_yield(); -#endif - } - - - static void setConcurrency (int n) { -#if defined(_WIN32) -#elif defined(__SVR4) - thr_setconcurrency (n); -#else - pthread_setconcurrency (n); -#endif - } - - -private: -#if defined(_WIN32) - typedef HANDLE FredType; -#else - typedef pthread_t FredType; - pthread_attr_t attr; -#endif - - FredType t; -}; - -} - - -#endif diff --git a/src/benchmarks/falsesharing/timer.h b/src/benchmarks/falsesharing/timer.h deleted file mode 100644 index d4d42c7..0000000 --- a/src/benchmarks/falsesharing/timer.h +++ /dev/null @@ -1,372 +0,0 @@ -/* -*- C++ -*- */ - -/* - - Heap Layers: An Extensible Memory Allocation Infrastructure - - Copyright (C) 2000-2003 by Emery Berger - http://www.cs.umass.edu/~emery - emery@cs.umass.edu - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include <cassert> -#include <stdio.h> - - -#ifndef _TIMER_H_ -#define _TIMER_H_ - -/** - * @class Timer - * @brief A portable class for high-resolution timing. - * - * This class simplifies timing measurements across a number of platforms. - * - * @code - * Timer t; - * t.start(); - * // do some work - * t.stop(); - * cout << "That took " << (double) t << " seconds." << endl; - * @endcode - * - */ - -#ifdef __APPLE__ -#include <sys/time.h> -#endif - -#if defined(__linux__) && defined(__GNUG__) && defined(__i386__) - -#include <stdio.h> -#include <limits.h> -#include <time.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> - -static void getTime (unsigned long& tlo, unsigned long& thi) { - asm volatile ("rdtsc" - : "=a"(tlo), - "=d" (thi)); -} - - -static double getFrequency (void) { - static double freq = 0.0; - static bool initialized = false; - unsigned long LTime0, LTime1, HTime0, HTime1; - if (!initialized) { - - freq = 2600000.0; - -#if 0 - // Compute MHz directly. - // Wait for approximately one second. - - getTime (LTime0, HTime0); - // printf ("waiting...\n"); - struct timespec rqtp, rmtp; - rqtp.tv_sec = 1; - rqtp.tv_nsec = 0; - nanosleep (&rqtp, &rmtp); - // printf ("done.\n"); - getTime (LTime1, HTime1); - - freq = (double)(LTime1 - LTime0) + (double)(UINT_MAX)*(double)(HTime1 - HTime0); - if (LTime1 < LTime0) { - freq -= (double)UINT_MAX; - } -#endif - initialized = true; - - } else { - // printf ("wha?\n"); - } - return freq; -} - - -namespace HL { - -class Timer { -public: - Timer (void) - : timeElapsed (0.0) - { - _frequency = getFrequency(); - // printf ("wooo!\n"); - // printf ("freq = %lf\n", frequency); - } - void start (void) { - getTime (currentLo, currentHi); - } - void stop (void) { - unsigned long lo, hi; - getTime (lo, hi); - double now = (double) hi * 4294967296.0 + lo; - double prev = (double) currentHi * 4294967296.0 + currentLo; - timeElapsed = (now - prev) / _frequency; - } - - operator double (void) { - return timeElapsed; - } - -private: - double timeElapsed; - unsigned long currentLo, currentHi; - double _frequency; -}; - -}; - -#else - - -#ifdef __SVR4 // Solaris -#include <sys/time.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/procfs.h> -#include <stdio.h> -#endif // __SVR4 - -#include <time.h> - -#if defined(unix) || defined(__linux) -#include <sys/time.h> -#include <unistd.h> -#endif - - -#ifdef __sgi -#include <sys/types.h> -#include <sys/times.h> -#include <limits.h> -#endif - - -#if defined(_WIN32) -#include <windows.h> -#endif - - -#if defined(__BEOS__) -#include <OS.h> -#endif - - -namespace HL { - -class Timer { - -public: - - /// Initializes the timer. - Timer (void) -#if !defined(_WIN32) - : _starttime (0), - _elapsedtime (0) -#endif - { - } - - /// Start the timer. - void start (void) { _starttime = _time(); } - - /// Stop the timer. - void stop (void) { _elapsedtime += _time() - _starttime; } - - /// Reset the timer. - void reset (void) { _starttime = _elapsedtime; } - -#if 0 - // Set the timer. - void set (double secs) { _starttime = 0; _elapsedtime = _sectotime (secs);} -#endif - - /// Return the number of seconds elapsed. - operator double (void) { return _timetosec (_elapsedtime); } - - static double currentTime (void) { TimeType t; t = _time(); return _timetosec (t); } - - -private: - - // The _timer variable will be different depending on the OS. - // We try to use the best timer available. - -#ifdef __sgi -#define TIMER_FOUND - - long _starttime, _elapsedtime; - - long _time (void) { - struct tms t; - long ticks = times (&t); - return ticks; - } - - static double _timetosec (long t) { - return ((double) (t) / CLK_TCK); - } - - static long _sectotime (double sec) { - return (long) sec * CLK_TCK; - } -#endif - -#ifdef __SVR4 // Solaris -#define TIMER_FOUND - typedef hrtime_t TimeType; - TimeType _starttime, _elapsedtime; - - static TimeType _time (void) { - return gethrtime(); - } - - static TimeType _sectotime (double sec) { return (hrtime_t) (sec * 1.0e9); } - - static double _timetosec (TimeType& t) { - return ((double) (t) / 1.0e9); - } -#endif // __SVR4 - -#if defined(MAC) || defined(macintosh) -#define TIMER_FOUND - double _starttime, _elapsedtime; - - double _time (void) { - return get_Mac_microseconds(); - } - - double _timetosec (hrtime_t& t) { - return t; - } -#endif // MAC - -#ifdef _WIN32 -#define TIMER_FOUND - -#ifndef __GNUC__ - class TimeType { - public: - TimeType (void) - { - largeInt.QuadPart = 0; - } - operator double& (void) { return (double&) largeInt.QuadPart; } - operator LARGE_INTEGER& (void) { return largeInt; } - double timeToSec (void) { - return (double) largeInt.QuadPart / getFreq(); - } - private: - double getFreq (void) { - QueryPerformanceFrequency (&freq); - return (double) freq.QuadPart; - } - - LARGE_INTEGER largeInt; - LARGE_INTEGER freq; - }; - - TimeType _starttime, _elapsedtime; - - static TimeType _time (void) { - TimeType t; - int r = QueryPerformanceCounter (&((LARGE_INTEGER&) t)); - assert (r); - return t; - } - - static double _timetosec (TimeType& t) { - return t.timeToSec(); - } -#else - typedef DWORD TimeType; - DWORD _starttime, _elapsedtime; - static DWORD _time (void) { - return GetTickCount(); - } - - static double _timetosec (DWORD& t) { - return (double) t / 100000.0; - } - static unsigned long _sectotime (double sec) { - return (unsigned long)(sec); - } -#endif -#endif // _WIN32 - - -#ifdef __BEOS__ -#define TIMER_FOUND - bigtime_t _starttime, _elapsedtime; - bigtime_t _time(void) { - return system_time(); - } - double _timetosec (bigtime_t& t) { - return (double) t / 1000000.0; - } - - bigtime_t _sectotime (double sec) { - return (bigtime_t)(sec * 1000000.0); - } -#endif // __BEOS__ - -#ifndef TIMER_FOUND - - typedef long TimeType; - TimeType _starttime, _elapsedtime; - - static TimeType _time (void) { - struct timeval t; - gettimeofday (&t, NULL); - return t.tv_sec * 1000000 + t.tv_usec; - } - - static double _timetosec (TimeType t) { - return ((double) (t) / 1000000.0); - } - - static TimeType _sectotime (double sec) { - return (TimeType) (sec * 1000000.0); - } - -#endif // TIMER_FOUND - -#undef TIMER_FOUND - -}; - - -#ifdef __SVR4 // Solaris -class VirtualTimer : public Timer { -public: - hrtime_t _time (void) { - return gethrvtime(); - } -}; -#endif - -} - -#endif - -#endif diff --git a/src/benchmarks/fd.py b/src/benchmarks/fd.py deleted file mode 100644 index 1fdd96a..0000000 --- a/src/benchmarks/fd.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the fd benchmark""" - -import os -import re -from urllib.request import urlretrieve - -from src.artifact import ArchiveArtifact, GitArtifact -from src.benchmark import Benchmark -import src.plots as plt -from src.util import print_info - - -class BenchmarkFd(Benchmark): - """fd benchmark - """ - def __init__(self): - name = "fd" - super().__init__(name) - - self.cmd = "fd -HI -e c '.*[0-9].*' {linux_files}" - - def prepare(self): - super().prepare() - - linux = GitArtifact( - "linux", - "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git") - linux_version = "v5.3" - self.linux_files = linux.provide(linux_version) - - if os.path.exists(self.build_dir): - return - - fd_version = "v7.4.0" - self.results["facts"]["versions"]["fd"] = fd_version - fd_url = ("https://github.com/sharkdp/fd/releases/latest/download/" - f"fd-{fd_version}-x86_64-unknown-linux-gnu.tar.gz") - - fd = ArchiveArtifact("fd", fd_url, "tar", - "a5d8e7c8484449aa324a46abfdfaf026d7de77ee") - - fd_dir = os.path.join(self.build_dir, "fd_sources") - fd.provide(fd_dir) - - # create symlinks - for exe in ["fd"]: - src = os.path.join(fd_dir, - f"fd-{fd_version}-x86_64-unknown-linux-gnu", - exe) - dest = os.path.join(self.build_dir, exe) - os.link(src, dest) - - def summary(self): - plt.plot(self, - "{task-clock}", - plot_type='bar', - fig_options={ - 'ylabel': "runtime in ms", - 'title': "fd runtime", - }, - file_postfix="runtime") - - plt.export_stats_to_dataref(self, "task-clock") - - plt.plot(self, - "{VmHWM}", - plot_type='bar', - fig_options={ - 'ylabel': "VmHWM in KB", - 'title': "fd memusage" - }, - file_postfix="memusage") - - plt.export_stats_to_dataref(self, "VmHWM") - - -fd = BenchmarkFd() diff --git a/src/benchmarks/httpd.py b/src/benchmarks/httpd.py deleted file mode 100644 index 18a9bf6..0000000 --- a/src/benchmarks/httpd.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the httpd benchmark""" - -import re - -from src.benchmark import Benchmark -import src.facter -import src.plots as plt - - -class BenchmarkHTTPD(Benchmark): - """TODO""" - def __init__(self): - name = "httpd" - - self.args = { - "nthreads": Benchmark.scale_threads_for_cpus(2), - "site": ["index.html", "index.php"] - } - self.cmd = "ab -n 10000 -c {nthreads} localhost:8080/{site}" - self.measure_cmd = "" - self.servers = [{"name": "nginx", - "cmd": "nginx -c {builddir}/benchmarks/httpd/etc/nginx/nginx.conf"}, - {"name": "php-fpm", - "cmd": "php-fpm -c {builddir}/benchmarks/httpd/etc/php/php.ini "\ - "-y {builddir}/benchmarks/httpd/etc/php/php-fpm.conf -F"}] - - self.requirements = ["nginx", "ab"] - - super().__init__(name) - - def prepare(self): - super().prepare() - - self.results["facts"]["versions"]["nginx"] = src.facter.exe_version( - "nginx", "-v") - self.results["facts"]["versions"]["ab"] = src.facter.exe_version( - "ab", "-V") - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - result["time"] = re.search( - "Time taken for tests:\\s*(\\d*\\.\\d*) seconds", stdout).group(1) - result["requests"] = re.search( - "Requests per second:\\s*(\\d*\\.\\d*) .*", stdout).group(1) - - def summary(self): - plt.plot(self, - "{requests}", - fig_options={ - 'xlabel': "threads", - 'ylabel': "requests/s", - 'title': "{perm.site}: requests/s", - 'autoticks': False, - }, - file_postfix="requests") - - plt.plot(self, - "{nginx_vmhwm}", - fig_options={ - 'xlabel': "threads", - 'ylabel': "VmHWM in KB", - 'title': "{perm.site}: nginx memory usage", - 'autoticks': False, - }, - file_postfix="httpd_vmhwm") - - plt.plot(self, - "{php-fpm_vmhwm}", - fig_options={ - 'xlabel': "threads", - 'ylabel': "VmHWM in KB", - 'title': "{perm.site}: php-fpm memory usage", - 'autoticks': False, - }, - file_postfix="php-fpm_vmhwm") - - -httpd = BenchmarkHTTPD() diff --git a/src/benchmarks/httpd/Makefile b/src/benchmarks/httpd/Makefile deleted file mode 100644 index dff3efe..0000000 --- a/src/benchmarks/httpd/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -OBJDIR ?= obj - -.PHONY = all clean - -all: $(OBJDIR)/html $(OBJDIR)/php $(OBJDIR)/etc/nginx $(OBJDIR)/etc/php $(OBJDIR)/logs $(OBJDIR)/run - -$(OBJDIR)/html: html | $(OBJDIR) - cp -r html $(OBJDIR)/html - -$(OBJDIR)/php: php | $(OBJDIR) - cp -r php $(OBJDIR)/php - -$(OBJDIR)/logs: | $(OBJDIR) - mkdir -p $@ - -$(OBJDIR)/run: | $(OBJDIR) - mkdir -p $@ - -$(OBJDIR)/etc/nginx: etc/nginx/nginx.conf | $(OBJDIR)/etc - mkdir -p $@ - sed "s|OBJDIR|$(OBJDIR)|" $< > $@/nginx.conf - -$(OBJDIR)/etc/php: etc/php/php.ini etc/php/php-fpm.conf etc/php/php-fpm.d/www.conf | $(OBJDIR) - mkdir -p $@/php-fpm.d/ - sed "s|OBJDIR|$(OBJDIR)|" etc/php/php.ini > $@/php.ini - sed "s|OBJDIR|$(OBJDIR)|" etc/php/php-fpm.conf > $@/php-fpm.conf - sed "s|OBJDIR|$(OBJDIR)|" etc/php/php-fpm.d/www.conf > $@/php-fpm.d/www.conf - -$(OBJDIR): - mkdir -p $@ - -$(OBJDIR)/etc: - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/httpd/etc/nginx/nginx.conf b/src/benchmarks/httpd/etc/nginx/nginx.conf deleted file mode 100644 index 278ea0b..0000000 --- a/src/benchmarks/httpd/etc/nginx/nginx.conf +++ /dev/null @@ -1,115 +0,0 @@ -#user html; -worker_processes 1; -daemon off; - - -error_log OBJDIR/logs/nginx-error.log; -error_log OBJDIR/logs/nginx-error.log notice; -error_log OBJDIR/logs/nginx-error.log info; - -pid OBJDIR/run/nginx.pid; - - -events { - worker_connections 1024; -} - - -http { - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log OBJDIR/logs/nginx-access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - server { - listen 8080; - server_name localhost; - - location / { - root OBJDIR/html; - index index.html index.htm; - } - - location ~ [^/]\.php(/|$) { - root OBJDIR/html; - # Correctly handle request like /test.php/foo/blah.php or /test.php/ - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - - try_files $uri $document_root$fastcgi_script_name =404; - - # Mitigate https://httpoxy.org/ vulnerabilities - fastcgi_param HTTP_PROXY ""; - - fastcgi_pass unix:OBJDIR/php-socket; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - - # fastcgi_params from arch linux nginx install - fastcgi_param QUERY_STRING $query_string; - fastcgi_param REQUEST_METHOD $request_method; - fastcgi_param CONTENT_TYPE $content_type; - fastcgi_param CONTENT_LENGTH $content_length; - - fastcgi_param SCRIPT_NAME $fastcgi_script_name; - fastcgi_param REQUEST_URI $request_uri; - fastcgi_param DOCUMENT_URI $document_uri; - fastcgi_param DOCUMENT_ROOT $document_root; - fastcgi_param SERVER_PROTOCOL $server_protocol; - fastcgi_param REQUEST_SCHEME $scheme; - fastcgi_param HTTPS $https if_not_empty; - - fastcgi_param GATEWAY_INTERFACE CGI/1.1; - fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - - fastcgi_param REMOTE_ADDR $remote_addr; - fastcgi_param REMOTE_PORT $remote_port; - fastcgi_param SERVER_ADDR $server_addr; - fastcgi_param SERVER_PORT $server_port; - fastcgi_param SERVER_NAME $server_name; - - # PHP only, required if PHP was built with --enable-force-cgi-redirect - fastcgi_param REDIRECT_STATUS 200; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - - } - - # HTTPS server - # - #server { - # listen 443 ssl; - # server_name localhost; - - # ssl_certificate cert.pem; - # ssl_certificate_key cert.key; - - # ssl_session_cache shared:SSL:1m; - # ssl_session_timeout 5m; - - # ssl_ciphers HIGH:!aNULL:!MD5; - # ssl_prefer_server_ciphers on; - - # location / { - # root html; - # index index.html index.htm; - # } - #} - -} diff --git a/src/benchmarks/httpd/etc/php/php-fpm.conf b/src/benchmarks/httpd/etc/php/php-fpm.conf deleted file mode 100644 index fa461cf..0000000 --- a/src/benchmarks/httpd/etc/php/php-fpm.conf +++ /dev/null @@ -1,144 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;; -; FPM Configuration ; -;;;;;;;;;;;;;;;;;;;;; - -; All relative paths in this configuration file are relative to PHP's install -; prefix (/usr). This prefix can be dynamically changed by using the -; '-p' argument from the command line. - -;;;;;;;;;;;;;;;;;; -; Global Options ; -;;;;;;;;;;;;;;;;;; - -[global] -; Pid file -; Note: the default prefix is /var -; Default Value: none -pid = OBJDIR/run/php-fpm.pid - -; Error log file -; If it's set to "syslog", log is sent to syslogd instead of being written -; into a local file. -; Note: the default prefix is /var -; Default Value: log/php-fpm.log -error_log = OBJDIR/logs/php-fpm.log - - -; syslog_facility is used to specify what type of program is logging the -; message. This lets syslogd specify that messages from different facilities -; will be handled differently. -; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) -; Default Value: daemon -;syslog.facility = daemon - -; syslog_ident is prepended to every message. If you have multiple FPM -; instances running on the same server, you can change the default value -; which must suit common needs. -; Default Value: php-fpm -;syslog.ident = php-fpm - -; Log level -; Possible Values: alert, error, warning, notice, debug -; Default Value: notice -;log_level = notice - -; Log limit on number of characters in the single line (log entry). If the -; line is over the limit, it is wrapped on multiple lines. The limit is for -; all logged characters including message prefix and suffix if present. However -; the new line character does not count into it as it is present only when -; logging to a file descriptor. It means the new line character is not present -; when logging to syslog. -; Default Value: 1024 -;log_limit = 4096 - -; Log buffering specifies if the log line is buffered which means that the -; line is written in a single write operation. If the value is false, then the -; data is written directly into the file descriptor. It is an experimental -; option that can potentionaly improve logging performance and memory usage -; for some heavy logging scenarios. This option is ignored if logging to syslog -; as it has to be always buffered. -; Default value: yes -;log_buffering = no - -; If this number of child processes exit with SIGSEGV or SIGBUS within the time -; interval set by emergency_restart_interval then FPM will restart. A value -; of '0' means 'Off'. -; Default Value: 0 -;emergency_restart_threshold = 0 - -; Interval of time used by emergency_restart_interval to determine when -; a graceful restart will be initiated. This can be useful to work around -; accidental corruptions in an accelerator's shared memory. -; Available Units: s(econds), m(inutes), h(ours), or d(ays) -; Default Unit: seconds -; Default Value: 0 -;emergency_restart_interval = 0 - -; Time limit for child processes to wait for a reaction on signals from master. -; Available units: s(econds), m(inutes), h(ours), or d(ays) -; Default Unit: seconds -; Default Value: 0 -;process_control_timeout = 0 - -; The maximum number of processes FPM will fork. This has been designed to control -; the global number of processes when using dynamic PM within a lot of pools. -; Use it with caution. -; Note: A value of 0 indicates no limit -; Default Value: 0 -; process.max = 128 - -; Specify the nice(2) priority to apply to the master process (only if set) -; The value can vary from -19 (highest priority) to 20 (lowest priority) -; Note: - It will only work if the FPM master process is launched as root -; - The pool process will inherit the master process priority -; unless specified otherwise -; Default Value: no set -; process.priority = -19 - -; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. -; Default Value: yes -;daemonize = yes - -; Set open file descriptor rlimit for the master process. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit for the master process. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Specify the event mechanism FPM will use. The following is available: -; - select (any POSIX os) -; - poll (any POSIX os) -; - epoll (linux >= 2.5.44) -; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) -; - /dev/poll (Solaris >= 7) -; - port (Solaris >= 10) -; Default Value: not set (auto detection) -;events.mechanism = epoll - -; When FPM is built with systemd integration, specify the interval, -; in seconds, between health report notification to systemd. -; Set to 0 to disable. -; Available Units: s(econds), m(inutes), h(ours) -; Default Unit: seconds -; Default value: 10 -;systemd_interval = 10 - -;;;;;;;;;;;;;;;;;;;; -; Pool Definitions ; -;;;;;;;;;;;;;;;;;;;; - -; Multiple pools of child processes may be started with different listening -; ports and different management options. The name of the pool will be -; used in logs and stats. There is no limitation on the number of pools which -; FPM can handle. Your system will tell you anyway :) - -; Include one or more files. If glob(3) exists, it is used to include a bunch of -; files from a glob(3) pattern. This directive can be used everywhere in the -; file. -; Relative path can also be used. They will be prefixed by: -; - the global prefix if it's been set (-p argument) -; - /usr otherwise -include=OBJDIR/etc/php/php-fpm.d/*.conf diff --git a/src/benchmarks/httpd/etc/php/php-fpm.d/www.conf b/src/benchmarks/httpd/etc/php/php-fpm.d/www.conf deleted file mode 100644 index 3f155db..0000000 --- a/src/benchmarks/httpd/etc/php/php-fpm.d/www.conf +++ /dev/null @@ -1,430 +0,0 @@ -; Start a new pool named 'www'. -; the variable $pool can be used in any directive and will be replaced by the -; pool name ('www' here) -[www] - -; Per pool prefix -; It only applies on the following directives: -; - 'access.log' -; - 'slowlog' -; - 'listen' (unixsocket) -; - 'chroot' -; - 'chdir' -; - 'php_values' -; - 'php_admin_values' -; When not set, the global prefix (or /usr) applies instead. -; Note: This directive can also be relative to the global prefix. -; Default Value: none -;prefix = /path/to/pools/$pool - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = http -group = http - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on -; a specific port; -; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses -; (IPv6 and IPv4-mapped) on a specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. -listen = OBJDIR/php-socket - -; Set listen(2) backlog. -; Default Value: 511 (-1 on FreeBSD and OpenBSD) -;listen.backlog = 511 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0660 -;listen.owner = http -;listen.group = http -;listen.mode = 0660 -; When POSIX Access Control Lists are supported you can set them using -; these options, value is a comma separated list of user/group names. -; When set, listen.owner and listen.group are ignored -;listen.acl_users = -;listen.acl_groups = - -; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -;listen.allowed_clients = 127.0.0.1 - -; Specify the nice(2) priority to apply to the pool processes (only if set) -; The value can vary from -19 (highest priority) to 20 (lower priority) -; Note: - It will only work if the FPM master process is launched as root -; - The pool processes will inherit the master process priority -; unless it specified otherwise -; Default Value: no set -; process.priority = -19 - -; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user -; or group is differrent than the master process user. It allows to create process -; core dump and ptrace the process for the pool user. -; Default Value: no -; process.dumpable = yes - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives. With this process management, there will be -; always at least 1 children. -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; ondemand - no children are created at startup. Children will be forked when -; new requests will connect. The following parameter are used: -; pm.max_children - the maximum number of children that -; can be alive at the same time. -; pm.process_idle_timeout - The number of seconds after which -; an idle process will be killed. -; Note: This value is mandatory. -pm = dynamic - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. The below defaults are based on a server without much resources. Don't -; forget to tweak pm.* to fit your needs. -; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' -; Note: This value is mandatory. -pm.max_children = 5 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.max_spare_servers = 3 - -; The number of seconds after which an idle process will be killed. -; Note: Used only when pm is set to 'ondemand' -; Default Value: 10s -;pm.process_idle_timeout = 10s; - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -;pm.max_requests = 500 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. It shows the following informations: -; pool - the name of the pool; -; process manager - static, dynamic or ondemand; -; start time - the date and time FPM has started; -; start since - number of seconds since FPM has started; -; accepted conn - the number of request accepted by the pool; -; listen queue - the number of request in the queue of pending -; connections (see backlog in listen(2)); -; max listen queue - the maximum number of requests in the queue -; of pending connections since FPM has started; -; listen queue len - the size of the socket queue of pending connections; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes; -; max active processes - the maximum number of active processes since FPM -; has started; -; max children reached - number of times, the process limit has been reached, -; when pm tries to start more children (works only for -; pm 'dynamic' and 'ondemand'); -; Value are updated in real time. -; Example output: -; pool: www -; process manager: static -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 62636 -; accepted conn: 190460 -; listen queue: 0 -; max listen queue: 1 -; listen queue len: 42 -; idle processes: 4 -; active processes: 11 -; total processes: 15 -; max active processes: 12 -; max children reached: 0 -; -; By default the status page output is formatted as text/plain. Passing either -; 'html', 'xml' or 'json' in the query string will return the corresponding -; output syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; http://www.foo.bar/status?xml -; -; By default the status page only outputs short status. Passing 'full' in the -; query string will also return status for each pool process. -; Example: -; http://www.foo.bar/status?full -; http://www.foo.bar/status?json&full -; http://www.foo.bar/status?html&full -; http://www.foo.bar/status?xml&full -; The Full status returns for each process: -; pid - the PID of the process; -; state - the state of the process (Idle, Running, ...); -; start time - the date and time the process has started; -; start since - the number of seconds since the process has started; -; requests - the number of requests the process has served; -; request duration - the duration in µs of the requests; -; request method - the request method (GET, POST, ...); -; request URI - the request URI with the query string; -; content length - the content length of the request (only with POST); -; user - the user (PHP_AUTH_USER) (or '-' if not set); -; script - the main script called (or '-' if not set); -; last request cpu - the %cpu the last request consumed -; it's always 0 if the process is not in Idle state -; because CPU calculation is done when the request -; processing has terminated; -; last request memory - the max amount of memory the last request consumed -; it's always 0 if the process is not in Idle state -; because memory calculation is done when the request -; processing has terminated; -; If the process is in Idle state, then informations are related to the -; last request the process has served. Otherwise informations are related to -; the current request being served. -; Example output: -; ************************ -; pid: 31330 -; state: Running -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 63087 -; requests: 12808 -; request duration: 1250261 -; request method: GET -; request URI: /test_mem.php?N=10000 -; content length: 0 -; user: - -; script: /home/fat/web/docs/php/test_mem.php -; last request cpu: 0.00 -; last request memory: 0 -; -; Note: There is a real-time FPM status monitoring sample web page available -; It's available in: /usr/share/php/fpm/status.html -; -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The access log file -; Default: not set -;access.log = log/$pool.access.log - -; The access log format. -; The following syntax is allowed -; %%: the '%' character -; %C: %CPU used by the request -; it can accept the following format: -; - %{user}C for user CPU only -; - %{system}C for system CPU only -; - %{total}C for user + system CPU (default) -; %d: time taken to serve the request -; it can accept the following format: -; - %{seconds}d (default) -; - %{miliseconds}d -; - %{mili}d -; - %{microseconds}d -; - %{micro}d -; %e: an environment variable (same as $_ENV or $_SERVER) -; it must be associated with embraces to specify the name of the env -; variable. Some exemples: -; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e -; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e -; %f: script filename -; %l: content-length of the request (for POST request only) -; %m: request method -; %M: peak of memory allocated by PHP -; it can accept the following format: -; - %{bytes}M (default) -; - %{kilobytes}M -; - %{kilo}M -; - %{megabytes}M -; - %{mega}M -; %n: pool name -; %o: output header -; it must be associated with embraces to specify the name of the header: -; - %{Content-Type}o -; - %{X-Powered-By}o -; - %{Transfert-Encoding}o -; - .... -; %p: PID of the child that serviced the request -; %P: PID of the parent of the child that serviced the request -; %q: the query string -; %Q: the '?' character if query string exists -; %r: the request URI (without the query string, see %q and %Q) -; %R: remote IP address -; %s: status (response code) -; %t: server time the request was received -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %T: time the log has been written (the request has finished) -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %u: remote user -; -; Default: "%R - %u %t \"%m %r\" %s" -;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -;slowlog = log/$pool.log.slow - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; Depth of slow log stack trace. -; Default Value: 20 -;request_slowlog_trace_depth = 20 - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_terminate_timeout = 0 - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: you can prefix with '$prefix' to chroot to the pool prefix or one -; of its subdirectories. If the pool prefix is not set, the global prefix -; will be used instead. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. -; Note: relative path can be used. -; Default Value: current directory or / when chroot -;chdir = /srv/http - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Note: on highloaded environement, this can cause some delay in the page -; process time (several ms). -; Default Value: no -;catch_workers_output = yes - -; Decorate worker output with prefix and suffix containing information about -; the child that writes to the log and if stdout or stderr is used as well as -; log level and time. This options is used only if catch_workers_output is yes. -; Settings to "no" will output data as written to the stdout or stderr. -; Default value: yes -;decorate_workers_output = no - -; Clear environment in FPM workers -; Prevents arbitrary environment variables from reaching FPM worker processes -; by clearing the environment in workers before env vars specified in this -; pool configuration are added. -; Setting to "no" will make all environment variables available to PHP code -; via getenv(), $_ENV and $_SERVER. -; Default Value: yes -;clear_env = no - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; execute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 .php7 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Note: path INI options can be relative and will be expanded with the prefix -; (pool, global or /usr) - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -;php_admin_value[error_log] = /var/log/fpm-php.www.log -;php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 32M diff --git a/src/benchmarks/httpd/etc/php/php.ini b/src/benchmarks/httpd/etc/php/php.ini deleted file mode 100644 index 13daf6b..0000000 --- a/src/benchmarks/httpd/etc/php/php.ini +++ /dev/null @@ -1,1945 +0,0 @@ -[PHP] - -;;;;;;;;;;;;;;;;;;; -; About php.ini ; -;;;;;;;;;;;;;;;;;;; -; PHP's initialization file, generally called php.ini, is responsible for -; configuring many of the aspects of PHP's behavior. - -; PHP attempts to find and load this configuration from a number of locations. -; The following is a summary of its search order: -; 1. SAPI module specific location. -; 2. The PHPRC environment variable. (As of PHP 5.2.0) -; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) -; 4. Current working directory (except CLI) -; 5. The web server's directory (for SAPI modules), or directory of PHP -; (otherwise in Windows) -; 6. The directory from the --with-config-file-path compile time option, or the -; Windows directory (usually C:\windows) -; See the PHP docs for more specific information. -; http://php.net/configuration.file - -; The syntax of the file is extremely simple. Whitespace and lines -; beginning with a semicolon are silently ignored (as you probably guessed). -; Section headers (e.g. [Foo]) are also silently ignored, even though -; they might mean something in the future. - -; Directives following the section heading [PATH=/www/mysite] only -; apply to PHP files in the /www/mysite directory. Directives -; following the section heading [HOST=www.example.com] only apply to -; PHP files served from www.example.com. Directives set in these -; special sections cannot be overridden by user-defined INI files or -; at runtime. Currently, [PATH=] and [HOST=] sections only work under -; CGI/FastCGI. -; http://php.net/ini.sections - -; Directives are specified using the following syntax: -; directive = value -; Directive names are *case sensitive* - foo=bar is different from FOO=bar. -; Directives are variables used to configure PHP or PHP extensions. -; There is no name validation. If PHP can't find an expected -; directive because it is not set or is mistyped, a default value will be used. - -; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one -; of the INI constants (On, Off, True, False, Yes, No and None) or an expression -; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a -; previously set variable or directive (e.g. ${foo}) - -; Expressions in the INI file are limited to bitwise operators and parentheses: -; | bitwise OR -; ^ bitwise XOR -; & bitwise AND -; ~ bitwise NOT -; ! boolean NOT - -; Boolean flags can be turned on using the values 1, On, True or Yes. -; They can be turned off using the values 0, Off, False or No. - -; An empty string can be denoted by simply not writing anything after the equal -; sign, or by using the None keyword: - -; foo = ; sets foo to an empty string -; foo = None ; sets foo to an empty string -; foo = "None" ; sets foo to the string 'None' - -; If you use constants in your value, and these constants belong to a -; dynamically loaded extension (either a PHP extension or a Zend extension), -; you may only use these constants *after* the line that loads the extension. - -;;;;;;;;;;;;;;;;;;; -; About this file ; -;;;;;;;;;;;;;;;;;;; -; PHP comes packaged with two INI files. One that is recommended to be used -; in production environments and one that is recommended to be used in -; development environments. - -; php.ini-production contains settings which hold security, performance and -; best practices at its core. But please be aware, these settings may break -; compatibility with older or less security conscience applications. We -; recommending using the production ini in production and testing environments. - -; php.ini-development is very similar to its production variant, except it is -; much more verbose when it comes to errors. We recommend using the -; development version only in development environments, as errors shown to -; application users can inadvertently leak otherwise secure information. - -; This is the php.ini-production INI file. - -;;;;;;;;;;;;;;;;;;; -; Quick Reference ; -;;;;;;;;;;;;;;;;;;; -; The following are all the settings which are different in either the production -; or development versions of the INIs with respect to PHP's default behavior. -; Please see the actual settings later in the document for more details as to why -; we recommend these changes in PHP's behavior. - -; display_errors -; Default Value: On -; Development Value: On -; Production Value: Off - -; display_startup_errors -; Default Value: Off -; Development Value: On -; Production Value: Off - -; error_reporting -; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED -; Development Value: E_ALL -; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT - -; html_errors -; Default Value: On -; Development Value: On -; Production value: On - -; log_errors -; Default Value: Off -; Development Value: On -; Production Value: On - -; max_input_time -; Default Value: -1 (Unlimited) -; Development Value: 60 (60 seconds) -; Production Value: 60 (60 seconds) - -; output_buffering -; Default Value: Off -; Development Value: 4096 -; Production Value: 4096 - -; register_argc_argv -; Default Value: On -; Development Value: Off -; Production Value: Off - -; request_order -; Default Value: None -; Development Value: "GP" -; Production Value: "GP" - -; session.gc_divisor -; Default Value: 100 -; Development Value: 1000 -; Production Value: 1000 - -; session.sid_bits_per_character -; Default Value: 4 -; Development Value: 5 -; Production Value: 5 - -; short_open_tag -; Default Value: On -; Development Value: Off -; Production Value: Off - -; track_errors -; Default Value: Off -; Development Value: On -; Production Value: Off - -; variables_order -; Default Value: "EGPCS" -; Development Value: "GPCS" -; Production Value: "GPCS" - -;;;;;;;;;;;;;;;;;;;; -; php.ini Options ; -;;;;;;;;;;;;;;;;;;;; -; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" -;user_ini.filename = ".user.ini" - -; To disable this feature set this option to an empty value -;user_ini.filename = - -; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) -;user_ini.cache_ttl = 300 - -;;;;;;;;;;;;;;;;;;;; -; Language Options ; -;;;;;;;;;;;;;;;;;;;; - -; Enable the PHP scripting language engine under Apache. -; http://php.net/engine -engine = On - -; This directive determines whether or not PHP will recognize code between -; <? and ?> tags as PHP source which should be processed as such. It is -; generally recommended that <?php and ?> should be used and that this feature -; should be disabled, as enabling it may result in issues when generating XML -; documents, however this remains supported for backward compatibility reasons. -; Note that this directive does not control the <?= shorthand tag, which can be -; used regardless of this directive. -; Default Value: On -; Development Value: Off -; Production Value: Off -; http://php.net/short-open-tag -short_open_tag = Off - -; The number of significant digits displayed in floating point numbers. -; http://php.net/precision -precision = 14 - -; Output buffering is a mechanism for controlling how much output data -; (excluding headers and cookies) PHP should keep internally before pushing that -; data to the client. If your application's output exceeds this setting, PHP -; will send that data in chunks of roughly the size you specify. -; Turning on this setting and managing its maximum buffer size can yield some -; interesting side-effects depending on your application and web server. -; You may be able to send headers and cookies after you've already sent output -; through print or echo. You also may see performance benefits if your server is -; emitting less packets due to buffered output versus PHP streaming the output -; as it gets it. On production servers, 4096 bytes is a good setting for performance -; reasons. -; Note: Output buffering can also be controlled via Output Buffering Control -; functions. -; Possible Values: -; On = Enabled and buffer is unlimited. (Use with caution) -; Off = Disabled -; Integer = Enables the buffer and sets its maximum size in bytes. -; Note: This directive is hardcoded to Off for the CLI SAPI -; Default Value: Off -; Development Value: 4096 -; Production Value: 4096 -; http://php.net/output-buffering -output_buffering = 4096 - -; You can redirect all of the output of your scripts to a function. For -; example, if you set output_handler to "mb_output_handler", character -; encoding will be transparently converted to the specified encoding. -; Setting any output handler automatically turns on output buffering. -; Note: People who wrote portable scripts should not depend on this ini -; directive. Instead, explicitly set the output handler using ob_start(). -; Using this ini directive may cause problems unless you know what script -; is doing. -; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" -; and you cannot use both "ob_gzhandler" and "zlib.output_compression". -; Note: output_handler must be empty if this is set 'On' !!!! -; Instead you must use zlib.output_handler. -; http://php.net/output-handler -;output_handler = - -; URL rewriter function rewrites URL on the fly by using -; output buffer. You can set target tags by this configuration. -; "form" tag is special tag. It will add hidden input tag to pass values. -; Refer to session.trans_sid_tags for usage. -; Default Value: "form=" -; Development Value: "form=" -; Production Value: "form=" -;url_rewriter.tags - -; URL rewriter will not rewrite absolute URL nor form by default. To enable -; absolute URL rewrite, allowed hosts must be defined at RUNTIME. -; Refer to session.trans_sid_hosts for more details. -; Default Value: "" -; Development Value: "" -; Production Value: "" -;url_rewriter.hosts - -; Transparent output compression using the zlib library -; Valid values for this option are 'off', 'on', or a specific buffer size -; to be used for compression (default is 4KB) -; Note: Resulting chunk size may vary due to nature of compression. PHP -; outputs chunks that are few hundreds bytes each as a result of -; compression. If you prefer a larger chunk size for better -; performance, enable output_buffering in addition. -; Note: You need to use zlib.output_handler instead of the standard -; output_handler, or otherwise the output will be corrupted. -; http://php.net/zlib.output-compression -zlib.output_compression = Off - -; http://php.net/zlib.output-compression-level -;zlib.output_compression_level = -1 - -; You cannot specify additional output handlers if zlib.output_compression -; is activated here. This setting does the same as output_handler but in -; a different order. -; http://php.net/zlib.output-handler -;zlib.output_handler = - -; Implicit flush tells PHP to tell the output layer to flush itself -; automatically after every output block. This is equivalent to calling the -; PHP function flush() after each and every call to print() or echo() and each -; and every HTML block. Turning this option on has serious performance -; implications and is generally recommended for debugging purposes only. -; http://php.net/implicit-flush -; Note: This directive is hardcoded to On for the CLI SAPI -implicit_flush = Off - -; The unserialize callback function will be called (with the undefined class' -; name as parameter), if the unserializer finds an undefined class -; which should be instantiated. A warning appears if the specified function is -; not defined, or if the function doesn't include/implement the missing class. -; So only set this entry, if you really want to implement such a -; callback-function. -unserialize_callback_func = - -; When floats & doubles are serialized, store serialize_precision significant -; digits after the floating point. The default value ensures that when floats -; are decoded with unserialize, the data will remain the same. -; The value is also used for json_encode when encoding double values. -; If -1 is used, then dtoa mode 0 is used which automatically select the best -; precision. -serialize_precision = -1 - -; open_basedir, if set, limits all file operations to the defined directory -; and below. This directive makes most sense if used in a per-directory -; or per-virtualhost web server configuration file. -; Note: disables the realpath cache -; http://php.net/open-basedir -;open_basedir = - -; This directive allows you to disable certain functions for security reasons. -; It receives a comma-delimited list of function names. -; http://php.net/disable-functions -disable_functions = - -; This directive allows you to disable certain classes for security reasons. -; It receives a comma-delimited list of class names. -; http://php.net/disable-classes -disable_classes = - -; Colors for Syntax Highlighting mode. Anything that's acceptable in -; <span style="color: ???????"> would work. -; http://php.net/syntax-highlighting -;highlight.string = #DD0000 -;highlight.comment = #FF9900 -;highlight.keyword = #007700 -;highlight.default = #0000BB -;highlight.html = #000000 - -; If enabled, the request will be allowed to complete even if the user aborts -; the request. Consider enabling it if executing long requests, which may end up -; being interrupted by the user or a browser timing out. PHP's default behavior -; is to disable this feature. -; http://php.net/ignore-user-abort -;ignore_user_abort = On - -; Determines the size of the realpath cache to be used by PHP. This value should -; be increased on systems where PHP opens many files to reflect the quantity of -; the file operations performed. -; Note: if open_basedir is set, the cache is disabled -; http://php.net/realpath-cache-size -;realpath_cache_size = 4096k - -; Duration of time, in seconds for which to cache realpath information for a given -; file or directory. For systems with rarely changing files, consider increasing this -; value. -; http://php.net/realpath-cache-ttl -;realpath_cache_ttl = 120 - -; Enables or disables the circular reference collector. -; http://php.net/zend.enable-gc -zend.enable_gc = On - -; If enabled, scripts may be written in encodings that are incompatible with -; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such -; encodings. To use this feature, mbstring extension must be enabled. -; Default: Off -;zend.multibyte = Off - -; Allows to set the default encoding for the scripts. This value will be used -; unless "declare(encoding=...)" directive appears at the top of the script. -; Only affects if zend.multibyte is set. -; Default: "" -;zend.script_encoding = - -;;;;;;;;;;;;;;;;; -; Miscellaneous ; -;;;;;;;;;;;;;;;;; - -; Decides whether PHP may expose the fact that it is installed on the server -; (e.g. by adding its signature to the Web server header). It is no security -; threat in any way, but it makes it possible to determine whether you use PHP -; on your server or not. -; http://php.net/expose-php -expose_php = On - -;;;;;;;;;;;;;;;;;;; -; Resource Limits ; -;;;;;;;;;;;;;;;;;;; - -; Maximum execution time of each script, in seconds -; http://php.net/max-execution-time -; Note: This directive is hardcoded to 0 for the CLI SAPI -max_execution_time = 30 - -; Maximum amount of time each script may spend parsing request data. It's a good -; idea to limit this time on productions servers in order to eliminate unexpectedly -; long running scripts. -; Note: This directive is hardcoded to -1 for the CLI SAPI -; Default Value: -1 (Unlimited) -; Development Value: 60 (60 seconds) -; Production Value: 60 (60 seconds) -; http://php.net/max-input-time -max_input_time = 60 - -; Maximum input variable nesting level -; http://php.net/max-input-nesting-level -;max_input_nesting_level = 64 - -; How many GET/POST/COOKIE input variables may be accepted -;max_input_vars = 1000 - -; Maximum amount of memory a script may consume (128MB) -; http://php.net/memory-limit -memory_limit = 128M - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Error handling and logging ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; This directive informs PHP of which errors, warnings and notices you would like -; it to take action for. The recommended way of setting values for this -; directive is through the use of the error level constants and bitwise -; operators. The error level constants are below here for convenience as well as -; some common settings and their meanings. -; By default, PHP is set to take action on all errors, notices and warnings EXCEPT -; those related to E_NOTICE and E_STRICT, which together cover best practices and -; recommended coding standards in PHP. For performance reasons, this is the -; recommend error reporting setting. Your production server shouldn't be wasting -; resources complaining about best practices and coding standards. That's what -; development servers and development settings are for. -; Note: The php.ini-development file has this setting as E_ALL. This -; means it pretty much reports everything which is exactly what you want during -; development and early testing. -; -; Error Level Constants: -; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) -; E_ERROR - fatal run-time errors -; E_RECOVERABLE_ERROR - almost fatal run-time errors -; E_WARNING - run-time warnings (non-fatal errors) -; E_PARSE - compile-time parse errors -; E_NOTICE - run-time notices (these are warnings which often result -; from a bug in your code, but it's possible that it was -; intentional (e.g., using an uninitialized variable and -; relying on the fact it is automatically initialized to an -; empty string) -; E_STRICT - run-time notices, enable to have PHP suggest changes -; to your code which will ensure the best interoperability -; and forward compatibility of your code -; E_CORE_ERROR - fatal errors that occur during PHP's initial startup -; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's -; initial startup -; E_COMPILE_ERROR - fatal compile-time errors -; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) -; E_USER_ERROR - user-generated error message -; E_USER_WARNING - user-generated warning message -; E_USER_NOTICE - user-generated notice message -; E_DEPRECATED - warn about code that will not work in future versions -; of PHP -; E_USER_DEPRECATED - user-generated deprecation warnings -; -; Common Values: -; E_ALL (Show all errors, warnings and notices including coding standards.) -; E_ALL & ~E_NOTICE (Show all errors, except for notices) -; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) -; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) -; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED -; Development Value: E_ALL -; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT -; http://php.net/error-reporting -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT - -; This directive controls whether or not and where PHP will output errors, -; notices and warnings too. Error output is very useful during development, but -; it could be very dangerous in production environments. Depending on the code -; which is triggering the error, sensitive information could potentially leak -; out of your application such as database usernames and passwords or worse. -; For production environments, we recommend logging errors rather than -; sending them to STDOUT. -; Possible Values: -; Off = Do not display any errors -; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) -; On or stdout = Display errors to STDOUT -; Default Value: On -; Development Value: On -; Production Value: Off -; http://php.net/display-errors -display_errors = Off - -; The display of errors which occur during PHP's startup sequence are handled -; separately from display_errors. PHP's default behavior is to suppress those -; errors from clients. Turning the display of startup errors on can be useful in -; debugging configuration problems. We strongly recommend you -; set this to 'off' for production servers. -; Default Value: Off -; Development Value: On -; Production Value: Off -; http://php.net/display-startup-errors -display_startup_errors = Off - -; Besides displaying errors, PHP can also log errors to locations such as a -; server-specific log, STDERR, or a location specified by the error_log -; directive found below. While errors should not be displayed on productions -; servers they should still be monitored and logging is a great way to do that. -; Default Value: Off -; Development Value: On -; Production Value: On -; http://php.net/log-errors -log_errors = On - -; Set maximum length of log_errors. In error_log information about the source is -; added. The default is 1024 and 0 allows to not apply any maximum length at all. -; http://php.net/log-errors-max-len -log_errors_max_len = 1024 - -; Do not log repeated messages. Repeated errors must occur in same file on same -; line unless ignore_repeated_source is set true. -; http://php.net/ignore-repeated-errors -ignore_repeated_errors = Off - -; Ignore source of message when ignoring repeated messages. When this setting -; is On you will not log errors with repeated messages from different files or -; source lines. -; http://php.net/ignore-repeated-source -ignore_repeated_source = Off - -; If this parameter is set to Off, then memory leaks will not be shown (on -; stdout or in the log). This has only effect in a debug compile, and if -; error reporting includes E_WARNING in the allowed list -; http://php.net/report-memleaks -report_memleaks = On - -; This setting is on by default. -;report_zend_debug = 0 - -; Store the last error/warning message in $php_errormsg (boolean). Setting this value -; to On can assist in debugging and is appropriate for development servers. It should -; however be disabled on production servers. -; This directive is DEPRECATED. -; Default Value: Off -; Development Value: Off -; Production Value: Off -; http://php.net/track-errors -;track_errors = Off - -; Turn off normal error reporting and emit XML-RPC error XML -; http://php.net/xmlrpc-errors -;xmlrpc_errors = 0 - -; An XML-RPC faultCode -;xmlrpc_error_number = 0 - -; When PHP displays or logs an error, it has the capability of formatting the -; error message as HTML for easier reading. This directive controls whether -; the error message is formatted as HTML or not. -; Note: This directive is hardcoded to Off for the CLI SAPI -; Default Value: On -; Development Value: On -; Production value: On -; http://php.net/html-errors -html_errors = On - -; If html_errors is set to On *and* docref_root is not empty, then PHP -; produces clickable error messages that direct to a page describing the error -; or function causing the error in detail. -; You can download a copy of the PHP manual from http://php.net/docs -; and change docref_root to the base URL of your local copy including the -; leading '/'. You must also specify the file extension being used including -; the dot. PHP's default behavior is to leave these settings empty, in which -; case no links to documentation are generated. -; Note: Never use this feature for production boxes. -; http://php.net/docref-root -; Examples -;docref_root = "/phpmanual/" - -; http://php.net/docref-ext -;docref_ext = .html - -; String to output before an error message. PHP's default behavior is to leave -; this setting blank. -; http://php.net/error-prepend-string -; Example: -;error_prepend_string = "<span style='color: #ff0000'>" - -; String to output after an error message. PHP's default behavior is to leave -; this setting blank. -; http://php.net/error-append-string -; Example: -;error_append_string = "</span>" - -; Log errors to specified file. PHP's default behavior is to leave this value -; empty. -; http://php.net/error-log -; Example: -;error_log = php_errors.log -; Log errors to syslog (Event Log on Windows). -;error_log = syslog - -; The syslog ident is a string which is prepended to every message logged -; to syslog. Only used when error_log is set to syslog. -;syslog.ident = php - -; The syslog facility is used to specify what type of program is logging -; the message. Only used when error_log is set to syslog. -;syslog.facility = user - -; Set this to disable filtering control characters (the default). -; Some loggers only accept NVT-ASCII, others accept anything that's not -; control characters. If your logger accepts everything, then no filtering -; is needed at all. -; Allowed values are: -; ascii (all printable ASCII characters and NL) -; no-ctrl (all characters except control characters) -; all (all characters) -; http://php.net/syslog.filter -;syslog.filter = ascii - -;windows.show_crt_warning -; Default value: 0 -; Development value: 0 -; Production value: 0 - -;;;;;;;;;;;;;;;;; -; Data Handling ; -;;;;;;;;;;;;;;;;; - -; The separator used in PHP generated URLs to separate arguments. -; PHP's default setting is "&". -; http://php.net/arg-separator.output -; Example: -;arg_separator.output = "&" - -; List of separator(s) used by PHP to parse input URLs into variables. -; PHP's default setting is "&". -; NOTE: Every character in this directive is considered as separator! -; http://php.net/arg-separator.input -; Example: -;arg_separator.input = ";&" - -; This directive determines which super global arrays are registered when PHP -; starts up. G,P,C,E & S are abbreviations for the following respective super -; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty -; paid for the registration of these arrays and because ENV is not as commonly -; used as the others, ENV is not recommended on productions servers. You -; can still get access to the environment variables through getenv() should you -; need to. -; Default Value: "EGPCS" -; Development Value: "GPCS" -; Production Value: "GPCS"; -; http://php.net/variables-order -variables_order = "GPCS" - -; This directive determines which super global data (G,P & C) should be -; registered into the super global array REQUEST. If so, it also determines -; the order in which that data is registered. The values for this directive -; are specified in the same manner as the variables_order directive, -; EXCEPT one. Leaving this value empty will cause PHP to use the value set -; in the variables_order directive. It does not mean it will leave the super -; globals array REQUEST empty. -; Default Value: None -; Development Value: "GP" -; Production Value: "GP" -; http://php.net/request-order -request_order = "GP" - -; This directive determines whether PHP registers $argv & $argc each time it -; runs. $argv contains an array of all the arguments passed to PHP when a script -; is invoked. $argc contains an integer representing the number of arguments -; that were passed when the script was invoked. These arrays are extremely -; useful when running scripts from the command line. When this directive is -; enabled, registering these variables consumes CPU cycles and memory each time -; a script is executed. For performance reasons, this feature should be disabled -; on production servers. -; Note: This directive is hardcoded to On for the CLI SAPI -; Default Value: On -; Development Value: Off -; Production Value: Off -; http://php.net/register-argc-argv -register_argc_argv = Off - -; When enabled, the ENV, REQUEST and SERVER variables are created when they're -; first used (Just In Time) instead of when the script starts. If these -; variables are not used within a script, having this directive on will result -; in a performance gain. The PHP directive register_argc_argv must be disabled -; for this directive to have any affect. -; http://php.net/auto-globals-jit -auto_globals_jit = On - -; Whether PHP will read the POST data. -; This option is enabled by default. -; Most likely, you won't want to disable this option globally. It causes $_POST -; and $_FILES to always be empty; the only way you will be able to read the -; POST data will be through the php://input stream wrapper. This can be useful -; to proxy requests or to process the POST data in a memory efficient fashion. -; http://php.net/enable-post-data-reading -;enable_post_data_reading = Off - -; Maximum size of POST data that PHP will accept. -; Its value may be 0 to disable the limit. It is ignored if POST data reading -; is disabled through enable_post_data_reading. -; http://php.net/post-max-size -post_max_size = 8M - -; Automatically add files before PHP document. -; http://php.net/auto-prepend-file -auto_prepend_file = - -; Automatically add files after PHP document. -; http://php.net/auto-append-file -auto_append_file = - -; By default, PHP will output a media type using the Content-Type header. To -; disable this, simply set it to be empty. -; -; PHP's built-in default media type is set to text/html. -; http://php.net/default-mimetype -default_mimetype = "text/html" - -; PHP's default character set is set to UTF-8. -; http://php.net/default-charset -default_charset = "UTF-8" - -; PHP internal character encoding is set to empty. -; If empty, default_charset is used. -; http://php.net/internal-encoding -;internal_encoding = - -; PHP input character encoding is set to empty. -; If empty, default_charset is used. -; http://php.net/input-encoding -;input_encoding = - -; PHP output character encoding is set to empty. -; If empty, default_charset is used. -; See also output_buffer. -; http://php.net/output-encoding -;output_encoding = - -;;;;;;;;;;;;;;;;;;;;;;;;; -; Paths and Directories ; -;;;;;;;;;;;;;;;;;;;;;;;;; - -; UNIX: "/path1:/path2" -;include_path = ".:/php/includes" -; -; Windows: "\path1;\path2" -;include_path = ".;c:\php\includes" -; -; PHP's default setting for include_path is ".;/path/to/php/pear" -; http://php.net/include-path - -; The root of the PHP pages, used only if nonempty. -; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root -; if you are running php as a CGI under any web server (other than IIS) -; see documentation for security issues. The alternate is to use the -; cgi.force_redirect configuration below -; http://php.net/doc-root -doc_root = - -; The directory under which PHP opens the script using /~username used only -; if nonempty. -; http://php.net/user-dir -user_dir = - -; Directory in which the loadable extensions (modules) reside. -; http://php.net/extension-dir -extension_dir = "/usr/lib/php/modules/" -; On windows: -;extension_dir = "ext" - -; Directory where the temporary files should be placed. -; Defaults to the system default (see sys_get_temp_dir) -;sys_temp_dir = "/tmp" - -; Whether or not to enable the dl() function. The dl() function does NOT work -; properly in multithreaded servers, such as IIS or Zeus, and is automatically -; disabled on them. -; http://php.net/enable-dl -enable_dl = Off - -; cgi.force_redirect is necessary to provide security running PHP as a CGI under -; most web servers. Left undefined, PHP turns this on by default. You can -; turn it off here AT YOUR OWN RISK -; **You CAN safely turn this off for IIS, in fact, you MUST.** -; http://php.net/cgi.force-redirect -;cgi.force_redirect = 1 - -; if cgi.nph is enabled it will force cgi to always sent Status: 200 with -; every request. PHP's default behavior is to disable this feature. -;cgi.nph = 1 - -; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape -; (iPlanet) web servers, you MAY need to set an environment variable name that PHP -; will look for to know it is OK to continue execution. Setting this variable MAY -; cause security issues, KNOW WHAT YOU ARE DOING FIRST. -; http://php.net/cgi.redirect-status-env -;cgi.redirect_status_env = - -; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's -; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok -; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting -; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting -; of zero causes PHP to behave as before. Default is 1. You should fix your scripts -; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. -; http://php.net/cgi.fix-pathinfo -;cgi.fix_pathinfo=1 - -; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside -; of the web tree and people will not be able to circumvent .htaccess security. -;cgi.discard_path=1 - -; FastCGI under IIS supports the ability to impersonate -; security tokens of the calling client. This allows IIS to define the -; security context that the request runs under. mod_fastcgi under Apache -; does not currently support this feature (03/17/2002) -; Set to 1 if running under IIS. Default is zero. -; http://php.net/fastcgi.impersonate -;fastcgi.impersonate = 1 - -; Disable logging through FastCGI connection. PHP's default behavior is to enable -; this feature. -;fastcgi.logging = 0 - -; cgi.rfc2616_headers configuration option tells PHP what type of headers to -; use when sending HTTP response code. If set to 0, PHP sends Status: header that -; is supported by Apache. When this option is set to 1, PHP will send -; RFC2616 compliant header. -; Default is zero. -; http://php.net/cgi.rfc2616-headers -;cgi.rfc2616_headers = 0 - -; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! -; (shebang) at the top of the running script. This line might be needed if the -; script support running both as stand-alone script and via PHP CGI<. PHP in CGI -; mode skips this line and ignores its content if this directive is turned on. -; http://php.net/cgi.check-shebang-line -;cgi.check_shebang_line=1 - -;;;;;;;;;;;;;;;; -; File Uploads ; -;;;;;;;;;;;;;;;; - -; Whether to allow HTTP file uploads. -; http://php.net/file-uploads -file_uploads = On - -; Temporary directory for HTTP uploaded files (will use system default if not -; specified). -; http://php.net/upload-tmp-dir -;upload_tmp_dir = - -; Maximum allowed size for uploaded files. -; http://php.net/upload-max-filesize -upload_max_filesize = 2M - -; Maximum number of files that can be uploaded via a single request -max_file_uploads = 20 - -;;;;;;;;;;;;;;;;;; -; Fopen wrappers ; -;;;;;;;;;;;;;;;;;; - -; Whether to allow the treatment of URLs (like http:// or ftp://) as files. -; http://php.net/allow-url-fopen -allow_url_fopen = On - -; Whether to allow include/require to open URLs (like http:// or ftp://) as files. -; http://php.net/allow-url-include -allow_url_include = Off - -; Define the anonymous ftp password (your email address). PHP's default setting -; for this is empty. -; http://php.net/from -;from="john@doe.com" - -; Define the User-Agent string. PHP's default setting for this is empty. -; http://php.net/user-agent -;user_agent="PHP" - -; Default timeout for socket based streams (seconds) -; http://php.net/default-socket-timeout -default_socket_timeout = 60 - -; If your scripts have to deal with files from Macintosh systems, -; or you are running on a Mac and need to deal with files from -; unix or win32 systems, setting this flag will cause PHP to -; automatically detect the EOL character in those files so that -; fgets() and file() will work regardless of the source of the file. -; http://php.net/auto-detect-line-endings -;auto_detect_line_endings = Off - -;;;;;;;;;;;;;;;;;;;;;; -; Dynamic Extensions ; -;;;;;;;;;;;;;;;;;;;;;; - -; If you wish to have an extension loaded automatically, use the following -; syntax: -; -; extension=modulename -; -; For example: -; -; extension=mysqli -; -; When the extension library to load is not located in the default extension -; directory, You may specify an absolute path to the library file: -; -; extension=/path/to/extension/mysqli.so -; -; Note : The syntax used in previous PHP versions ('extension=<ext>.so' and -; 'extension='php_<ext>.dll') is supported for legacy reasons and may be -; deprecated in a future PHP major version. So, when it is possible, please -; move to the new ('extension=<ext>) syntax. -; -;extension=bcmath -;extension=bz2 -;extension=calendar -extension=curl -;extension=dba -;extension=enchant -;extension=exif -;extension=ftp -;extension=gd -;extension=gettext -;extension=gmp -;extension=iconv -;extension=imap -;extension=intl -;extension=sodium -;extension=ldap -;extension=mysqli -;extension=odbc -;zend_extension=opcache -;extension=pdo_dblib -;extension=pdo_mysql -;extension=pdo_odbc -;extension=pdo_pgsql -;extension=pdo_sqlite -;extension=pgsql -;extension=pspell -;extension=shmop -;extension=snmp -;extension=soap -;extension=sockets -;extension=sqlite3 -;extension=sysvmsg -;extension=sysvsem -;extension=sysvshm -;extension=tidy -;extension=xmlrpc -;extension=xsl -extension=zip - -;;;;;;;;;;;;;;;;;;; -; Module Settings ; -;;;;;;;;;;;;;;;;;;; - -[CLI Server] -; Whether the CLI web server uses ANSI color coding in its terminal output. -cli_server.color = On - -[Date] -; Defines the default timezone used by the date functions -; http://php.net/date.timezone -;date.timezone = - -; http://php.net/date.default-latitude -;date.default_latitude = 31.7667 - -; http://php.net/date.default-longitude -;date.default_longitude = 35.2333 - -; http://php.net/date.sunrise-zenith -;date.sunrise_zenith = 90.583333 - -; http://php.net/date.sunset-zenith -;date.sunset_zenith = 90.583333 - -[filter] -; http://php.net/filter.default -;filter.default = unsafe_raw - -; http://php.net/filter.default-flags -;filter.default_flags = - -[iconv] -; Use of this INI entry is deprecated, use global input_encoding instead. -; If empty, default_charset or input_encoding or iconv.input_encoding is used. -; The precedence is: default_charset < input_encoding < iconv.input_encoding -;iconv.input_encoding = - -; Use of this INI entry is deprecated, use global internal_encoding instead. -; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. -; The precedence is: default_charset < internal_encoding < iconv.internal_encoding -;iconv.internal_encoding = - -; Use of this INI entry is deprecated, use global output_encoding instead. -; If empty, default_charset or output_encoding or iconv.output_encoding is used. -; The precedence is: default_charset < output_encoding < iconv.output_encoding -; To use an output encoding conversion, iconv's output handler must be set -; otherwise output encoding conversion cannot be performed. -;iconv.output_encoding = - -[imap] -; rsh/ssh logins are disabled by default. Use this INI entry if you want to -; enable them. Note that the IMAP library does not filter mailbox names before -; passing them to rsh/ssh command, thus passing untrusted data to this function -; with rsh/ssh enabled is insecure. -;imap.enable_insecure_rsh=0 - -[intl] -;intl.default_locale = -; This directive allows you to produce PHP errors when some error -; happens within intl functions. The value is the level of the error produced. -; Default is 0, which does not produce any errors. -;intl.error_level = E_WARNING -;intl.use_exceptions = 0 - -[sqlite3] -; Directory pointing to SQLite3 extensions -; http://php.net/sqlite3.extension-dir -;sqlite3.extension_dir = - -; SQLite defensive mode flag (only available from SQLite 3.26+) -; When the defensive flag is enabled, language features that allow ordinary -; SQL to deliberately corrupt the database file are disabled. This forbids -; writing directly to the schema, shadow tables (eg. FTS data tables), or -; the sqlite_dbpage virtual table. -; https://www.sqlite.org/c3ref/c_dbconfig_defensive.html -; (for older SQLite versions, this flag has no use) -;sqlite3.defensive = 1 - -[Pcre] -; PCRE library backtracking limit. -; http://php.net/pcre.backtrack-limit -;pcre.backtrack_limit=100000 - -; PCRE library recursion limit. -; Please note that if you set this value to a high number you may consume all -; the available process stack and eventually crash PHP (due to reaching the -; stack size limit imposed by the Operating System). -; http://php.net/pcre.recursion-limit -;pcre.recursion_limit=100000 - -; Enables or disables JIT compilation of patterns. This requires the PCRE -; library to be compiled with JIT support. -;pcre.jit=1 - -[Pdo] -; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" -; http://php.net/pdo-odbc.connection-pooling -;pdo_odbc.connection_pooling=strict - -;pdo_odbc.db2_instance_name - -[Pdo_mysql] -; Default socket name for local MySQL connects. If empty, uses the built-in -; MySQL defaults. -pdo_mysql.default_socket= - -[Phar] -; http://php.net/phar.readonly -;phar.readonly = On - -; http://php.net/phar.require-hash -;phar.require_hash = On - -;phar.cache_list = - -[mail function] -; For Win32 only. -; http://php.net/smtp -SMTP = localhost -; http://php.net/smtp-port -smtp_port = 25 - -; For Win32 only. -; http://php.net/sendmail-from -;sendmail_from = me@example.com - -; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). -; http://php.net/sendmail-path -;sendmail_path = - -; Force the addition of the specified parameters to be passed as extra parameters -; to the sendmail binary. These parameters will always replace the value of -; the 5th parameter to mail(). -;mail.force_extra_parameters = - -; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename -mail.add_x_header = Off - -; The path to a log file that will log all mail() calls. Log entries include -; the full path of the script, line number, To address and headers. -;mail.log = -; Log mail to syslog (Event Log on Windows). -;mail.log = syslog - -[ODBC] -; http://php.net/odbc.default-db -;odbc.default_db = Not yet implemented - -; http://php.net/odbc.default-user -;odbc.default_user = Not yet implemented - -; http://php.net/odbc.default-pw -;odbc.default_pw = Not yet implemented - -; Controls the ODBC cursor model. -; Default: SQL_CURSOR_STATIC (default). -;odbc.default_cursortype - -; Allow or prevent persistent links. -; http://php.net/odbc.allow-persistent -odbc.allow_persistent = On - -; Check that a connection is still valid before reuse. -; http://php.net/odbc.check-persistent -odbc.check_persistent = On - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/odbc.max-persistent -odbc.max_persistent = -1 - -; Maximum number of links (persistent + non-persistent). -1 means no limit. -; http://php.net/odbc.max-links -odbc.max_links = -1 - -; Handling of LONG fields. Returns number of bytes to variables. 0 means -; passthru. -; http://php.net/odbc.defaultlrl -odbc.defaultlrl = 4096 - -; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. -; See the documentation on odbc_binmode and odbc_longreadlen for an explanation -; of odbc.defaultlrl and odbc.defaultbinmode -; http://php.net/odbc.defaultbinmode -odbc.defaultbinmode = 1 - -[Interbase] -; Allow or prevent persistent links. -ibase.allow_persistent = 1 - -; Maximum number of persistent links. -1 means no limit. -ibase.max_persistent = -1 - -; Maximum number of links (persistent + non-persistent). -1 means no limit. -ibase.max_links = -1 - -; Default database name for ibase_connect(). -;ibase.default_db = - -; Default username for ibase_connect(). -;ibase.default_user = - -; Default password for ibase_connect(). -;ibase.default_password = - -; Default charset for ibase_connect(). -;ibase.default_charset = - -; Default timestamp format. -ibase.timestampformat = "%Y-%m-%d %H:%M:%S" - -; Default date format. -ibase.dateformat = "%Y-%m-%d" - -; Default time format. -ibase.timeformat = "%H:%M:%S" - -[MySQLi] - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/mysqli.max-persistent -mysqli.max_persistent = -1 - -; Allow accessing, from PHP's perspective, local files with LOAD DATA statements -; http://php.net/mysqli.allow_local_infile -;mysqli.allow_local_infile = On - -; Allow or prevent persistent links. -; http://php.net/mysqli.allow-persistent -mysqli.allow_persistent = On - -; Maximum number of links. -1 means no limit. -; http://php.net/mysqli.max-links -mysqli.max_links = -1 - -; Default port number for mysqli_connect(). If unset, mysqli_connect() will use -; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the -; compile-time value defined MYSQL_PORT (in that order). Win32 will only look -; at MYSQL_PORT. -; http://php.net/mysqli.default-port -mysqli.default_port = 3306 - -; Default socket name for local MySQL connects. If empty, uses the built-in -; MySQL defaults. -; http://php.net/mysqli.default-socket -mysqli.default_socket = - -; Default host for mysql_connect() (doesn't apply in safe mode). -; http://php.net/mysqli.default-host -mysqli.default_host = - -; Default user for mysql_connect() (doesn't apply in safe mode). -; http://php.net/mysqli.default-user -mysqli.default_user = - -; Default password for mysqli_connect() (doesn't apply in safe mode). -; Note that this is generally a *bad* idea to store passwords in this file. -; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") -; and reveal this password! And of course, any users with read access to this -; file will be able to reveal the password as well. -; http://php.net/mysqli.default-pw -mysqli.default_pw = - -; Allow or prevent reconnect -mysqli.reconnect = Off - -[mysqlnd] -; Enable / Disable collection of general statistics by mysqlnd which can be -; used to tune and monitor MySQL operations. -mysqlnd.collect_statistics = On - -; Enable / Disable collection of memory usage statistics by mysqlnd which can be -; used to tune and monitor MySQL operations. -mysqlnd.collect_memory_statistics = Off - -; Records communication from all extensions using mysqlnd to the specified log -; file. -; http://php.net/mysqlnd.debug -;mysqlnd.debug = - -; Defines which queries will be logged. -;mysqlnd.log_mask = 0 - -; Default size of the mysqlnd memory pool, which is used by result sets. -;mysqlnd.mempool_default_size = 16000 - -; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. -;mysqlnd.net_cmd_buffer_size = 2048 - -; Size of a pre-allocated buffer used for reading data sent by the server in -; bytes. -;mysqlnd.net_read_buffer_size = 32768 - -; Timeout for network requests in seconds. -;mysqlnd.net_read_timeout = 31536000 - -; SHA-256 Authentication Plugin related. File with the MySQL server public RSA -; key. -;mysqlnd.sha256_server_public_key = - -[OCI8] - -; Connection: Enables privileged connections using external -; credentials (OCI_SYSOPER, OCI_SYSDBA) -; http://php.net/oci8.privileged-connect -;oci8.privileged_connect = Off - -; Connection: The maximum number of persistent OCI8 connections per -; process. Using -1 means no limit. -; http://php.net/oci8.max-persistent -;oci8.max_persistent = -1 - -; Connection: The maximum number of seconds a process is allowed to -; maintain an idle persistent connection. Using -1 means idle -; persistent connections will be maintained forever. -; http://php.net/oci8.persistent-timeout -;oci8.persistent_timeout = -1 - -; Connection: The number of seconds that must pass before issuing a -; ping during oci_pconnect() to check the connection validity. When -; set to 0, each oci_pconnect() will cause a ping. Using -1 disables -; pings completely. -; http://php.net/oci8.ping-interval -;oci8.ping_interval = 60 - -; Connection: Set this to a user chosen connection class to be used -; for all pooled server requests with Oracle 11g Database Resident -; Connection Pooling (DRCP). To use DRCP, this value should be set to -; the same string for all web servers running the same application, -; the database pool must be configured, and the connection string must -; specify to use a pooled server. -;oci8.connection_class = - -; High Availability: Using On lets PHP receive Fast Application -; Notification (FAN) events generated when a database node fails. The -; database must also be configured to post FAN events. -;oci8.events = Off - -; Tuning: This option enables statement caching, and specifies how -; many statements to cache. Using 0 disables statement caching. -; http://php.net/oci8.statement-cache-size -;oci8.statement_cache_size = 20 - -; Tuning: Enables statement prefetching and sets the default number of -; rows that will be fetched automatically after statement execution. -; http://php.net/oci8.default-prefetch -;oci8.default_prefetch = 100 - -; Compatibility. Using On means oci_close() will not close -; oci_connect() and oci_new_connect() connections. -; http://php.net/oci8.old-oci-close-semantics -;oci8.old_oci_close_semantics = Off - -[PostgreSQL] -; Allow or prevent persistent links. -; http://php.net/pgsql.allow-persistent -pgsql.allow_persistent = On - -; Detect broken persistent links always with pg_pconnect(). -; Auto reset feature requires a little overheads. -; http://php.net/pgsql.auto-reset-persistent -pgsql.auto_reset_persistent = Off - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/pgsql.max-persistent -pgsql.max_persistent = -1 - -; Maximum number of links (persistent+non persistent). -1 means no limit. -; http://php.net/pgsql.max-links -pgsql.max_links = -1 - -; Ignore PostgreSQL backends Notice message or not. -; Notice message logging require a little overheads. -; http://php.net/pgsql.ignore-notice -pgsql.ignore_notice = 0 - -; Log PostgreSQL backends Notice message or not. -; Unless pgsql.ignore_notice=0, module cannot log notice message. -; http://php.net/pgsql.log-notice -pgsql.log_notice = 0 - -[bcmath] -; Number of decimal digits for all bcmath functions. -; http://php.net/bcmath.scale -bcmath.scale = 0 - -[browscap] -; http://php.net/browscap -;browscap = extra/browscap.ini - -[Session] -; Handler used to store/retrieve data. -; http://php.net/session.save-handler -session.save_handler = files - -; Argument passed to save_handler. In the case of files, this is the path -; where data files are stored. Note: Windows users have to change this -; variable in order to use PHP's session functions. -; -; The path can be defined as: -; -; session.save_path = "N;/path" -; -; where N is an integer. Instead of storing all the session files in -; /path, what this will do is use subdirectories N-levels deep, and -; store the session data in those directories. This is useful if -; your OS has problems with many files in one directory, and is -; a more efficient layout for servers that handle many sessions. -; -; NOTE 1: PHP will not create this directory structure automatically. -; You can use the script in the ext/session dir for that purpose. -; NOTE 2: See the section on garbage collection below if you choose to -; use subdirectories for session storage -; -; The file storage module creates files using mode 600 by default. -; You can change that by using -; -; session.save_path = "N;MODE;/path" -; -; where MODE is the octal representation of the mode. Note that this -; does not overwrite the process's umask. -; http://php.net/session.save-path -;session.save_path = "/tmp" - -; Whether to use strict session mode. -; Strict session mode does not accept an uninitialized session ID, and -; regenerates the session ID if the browser sends an uninitialized session ID. -; Strict mode protects applications from session fixation via a session adoption -; vulnerability. It is disabled by default for maximum compatibility, but -; enabling it is encouraged. -; https://wiki.php.net/rfc/strict_sessions -session.use_strict_mode = 0 - -; Whether to use cookies. -; http://php.net/session.use-cookies -session.use_cookies = 1 - -; http://php.net/session.cookie-secure -;session.cookie_secure = - -; This option forces PHP to fetch and use a cookie for storing and maintaining -; the session id. We encourage this operation as it's very helpful in combating -; session hijacking when not specifying and managing your own session id. It is -; not the be-all and end-all of session hijacking defense, but it's a good start. -; http://php.net/session.use-only-cookies -session.use_only_cookies = 1 - -; Name of the session (used as cookie name). -; http://php.net/session.name -session.name = PHPSESSID - -; Initialize session on request startup. -; http://php.net/session.auto-start -session.auto_start = 0 - -; Lifetime in seconds of cookie or, if 0, until browser is restarted. -; http://php.net/session.cookie-lifetime -session.cookie_lifetime = 0 - -; The path for which the cookie is valid. -; http://php.net/session.cookie-path -session.cookie_path = / - -; The domain for which the cookie is valid. -; http://php.net/session.cookie-domain -session.cookie_domain = - -; Whether or not to add the httpOnly flag to the cookie, which makes it -; inaccessible to browser scripting languages such as JavaScript. -; http://php.net/session.cookie-httponly -session.cookie_httponly = - -; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) -; Current valid values are "Lax" or "Strict" -; https://tools.ietf.org/html/draft-west-first-party-cookies-07 -session.cookie_samesite = - -; Handler used to serialize data. php is the standard serializer of PHP. -; http://php.net/session.serialize-handler -session.serialize_handler = php - -; Defines the probability that the 'garbage collection' process is started -; on every session initialization. The probability is calculated by using -; gc_probability/gc_divisor. Where session.gc_probability is the numerator -; and gc_divisor is the denominator in the equation. Setting this value to 1 -; when the session.gc_divisor value is 100 will give you approximately a 1% chance -; the gc will run on any given request. -; Default Value: 1 -; Development Value: 1 -; Production Value: 1 -; http://php.net/session.gc-probability -session.gc_probability = 1 - -; Defines the probability that the 'garbage collection' process is started on every -; session initialization. The probability is calculated by using the following equation: -; gc_probability/gc_divisor. Where session.gc_probability is the numerator and -; session.gc_divisor is the denominator in the equation. Setting this value to 100 -; when the session.gc_probability value is 1 will give you approximately a 1% chance -; the gc will run on any given request. Increasing this value to 1000 will give you -; a 0.1% chance the gc will run on any given request. For high volume production servers, -; this is a more efficient approach. -; Default Value: 100 -; Development Value: 1000 -; Production Value: 1000 -; http://php.net/session.gc-divisor -session.gc_divisor = 1000 - -; After this number of seconds, stored data will be seen as 'garbage' and -; cleaned up by the garbage collection process. -; http://php.net/session.gc-maxlifetime -session.gc_maxlifetime = 1440 - -; NOTE: If you are using the subdirectory option for storing session files -; (see session.save_path above), then garbage collection does *not* -; happen automatically. You will need to do your own garbage -; collection through a shell script, cron entry, or some other method. -; For example, the following script would is the equivalent of -; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): -; find /path/to/sessions -cmin +24 -type f | xargs rm - -; Check HTTP Referer to invalidate externally stored URLs containing ids. -; HTTP_REFERER has to contain this substring for the session to be -; considered as valid. -; http://php.net/session.referer-check -session.referer_check = - -; Set to {nocache,private,public,} to determine HTTP caching aspects -; or leave this empty to avoid sending anti-caching headers. -; http://php.net/session.cache-limiter -session.cache_limiter = nocache - -; Document expires after n minutes. -; http://php.net/session.cache-expire -session.cache_expire = 180 - -; trans sid support is disabled by default. -; Use of trans sid may risk your users' security. -; Use this option with caution. -; - User may send URL contains active session ID -; to other person via. email/irc/etc. -; - URL that contains active session ID may be stored -; in publicly accessible computer. -; - User may access your site with the same session ID -; always using URL stored in browser's history or bookmarks. -; http://php.net/session.use-trans-sid -session.use_trans_sid = 0 - -; Set session ID character length. This value could be between 22 to 256. -; Shorter length than default is supported only for compatibility reason. -; Users should use 32 or more chars. -; http://php.net/session.sid-length -; Default Value: 32 -; Development Value: 26 -; Production Value: 26 -session.sid_length = 26 - -; The URL rewriter will look for URLs in a defined set of HTML tags. -; <form> is special; if you include them here, the rewriter will -; add a hidden <input> field with the info which is otherwise appended -; to URLs. <form> tag's action attribute URL will not be modified -; unless it is specified. -; Note that all valid entries require a "=", even if no value follows. -; Default Value: "a=href,area=href,frame=src,form=" -; Development Value: "a=href,area=href,frame=src,form=" -; Production Value: "a=href,area=href,frame=src,form=" -; http://php.net/url-rewriter.tags -session.trans_sid_tags = "a=href,area=href,frame=src,form=" - -; URL rewriter does not rewrite absolute URLs by default. -; To enable rewrites for absolute paths, target hosts must be specified -; at RUNTIME. i.e. use ini_set() -; <form> tags is special. PHP will check action attribute's URL regardless -; of session.trans_sid_tags setting. -; If no host is defined, HTTP_HOST will be used for allowed host. -; Example value: php.net,www.php.net,wiki.php.net -; Use "," for multiple hosts. No spaces are allowed. -; Default Value: "" -; Development Value: "" -; Production Value: "" -;session.trans_sid_hosts="" - -; Define how many bits are stored in each character when converting -; the binary hash data to something readable. -; Possible values: -; 4 (4 bits: 0-9, a-f) -; 5 (5 bits: 0-9, a-v) -; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") -; Default Value: 4 -; Development Value: 5 -; Production Value: 5 -; http://php.net/session.hash-bits-per-character -session.sid_bits_per_character = 5 - -; Enable upload progress tracking in $_SESSION -; Default Value: On -; Development Value: On -; Production Value: On -; http://php.net/session.upload-progress.enabled -;session.upload_progress.enabled = On - -; Cleanup the progress information as soon as all POST data has been read -; (i.e. upload completed). -; Default Value: On -; Development Value: On -; Production Value: On -; http://php.net/session.upload-progress.cleanup -;session.upload_progress.cleanup = On - -; A prefix used for the upload progress key in $_SESSION -; Default Value: "upload_progress_" -; Development Value: "upload_progress_" -; Production Value: "upload_progress_" -; http://php.net/session.upload-progress.prefix -;session.upload_progress.prefix = "upload_progress_" - -; The index name (concatenated with the prefix) in $_SESSION -; containing the upload progress information -; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" -; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" -; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" -; http://php.net/session.upload-progress.name -;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" - -; How frequently the upload progress should be updated. -; Given either in percentages (per-file), or in bytes -; Default Value: "1%" -; Development Value: "1%" -; Production Value: "1%" -; http://php.net/session.upload-progress.freq -;session.upload_progress.freq = "1%" - -; The minimum delay between updates, in seconds -; Default Value: 1 -; Development Value: 1 -; Production Value: 1 -; http://php.net/session.upload-progress.min-freq -;session.upload_progress.min_freq = "1" - -; Only write session data when session data is changed. Enabled by default. -; http://php.net/session.lazy-write -;session.lazy_write = On - -[Assertion] -; Switch whether to compile assertions at all (to have no overhead at run-time) -; -1: Do not compile at all -; 0: Jump over assertion at run-time -; 1: Execute assertions -; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) -; Default Value: 1 -; Development Value: 1 -; Production Value: -1 -; http://php.net/zend.assertions -zend.assertions = -1 - -; Assert(expr); active by default. -; http://php.net/assert.active -;assert.active = On - -; Throw an AssertionError on failed assertions -; http://php.net/assert.exception -;assert.exception = On - -; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) -; http://php.net/assert.warning -;assert.warning = On - -; Don't bail out by default. -; http://php.net/assert.bail -;assert.bail = Off - -; User-function to be called if an assertion fails. -; http://php.net/assert.callback -;assert.callback = 0 - -; Eval the expression with current error_reporting(). Set to true if you want -; error_reporting(0) around the eval(). -; http://php.net/assert.quiet-eval -;assert.quiet_eval = 0 - -[COM] -; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs -; http://php.net/com.typelib-file -;com.typelib_file = - -; allow Distributed-COM calls -; http://php.net/com.allow-dcom -;com.allow_dcom = true - -; autoregister constants of a component's typlib on com_load() -; http://php.net/com.autoregister-typelib -;com.autoregister_typelib = true - -; register constants casesensitive -; http://php.net/com.autoregister-casesensitive -;com.autoregister_casesensitive = false - -; show warnings on duplicate constant registrations -; http://php.net/com.autoregister-verbose -;com.autoregister_verbose = true - -; The default character set code-page to use when passing strings to and from COM objects. -; Default: system ANSI code page -;com.code_page= - -[mbstring] -; language for internal character representation. -; This affects mb_send_mail() and mbstring.detect_order. -; http://php.net/mbstring.language -;mbstring.language = Japanese - -; Use of this INI entry is deprecated, use global internal_encoding instead. -; internal/script encoding. -; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) -; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. -; The precedence is: default_charset < internal_encoding < iconv.internal_encoding -;mbstring.internal_encoding = - -; Use of this INI entry is deprecated, use global input_encoding instead. -; http input encoding. -; mbstring.encoding_translation = On is needed to use this setting. -; If empty, default_charset or input_encoding or mbstring.input is used. -; The precedence is: default_charset < input_encoding < mbsting.http_input -; http://php.net/mbstring.http-input -;mbstring.http_input = - -; Use of this INI entry is deprecated, use global output_encoding instead. -; http output encoding. -; mb_output_handler must be registered as output buffer to function. -; If empty, default_charset or output_encoding or mbstring.http_output is used. -; The precedence is: default_charset < output_encoding < mbstring.http_output -; To use an output encoding conversion, mbstring's output handler must be set -; otherwise output encoding conversion cannot be performed. -; http://php.net/mbstring.http-output -;mbstring.http_output = - -; enable automatic encoding translation according to -; mbstring.internal_encoding setting. Input chars are -; converted to internal encoding by setting this to On. -; Note: Do _not_ use automatic encoding translation for -; portable libs/applications. -; http://php.net/mbstring.encoding-translation -;mbstring.encoding_translation = Off - -; automatic encoding detection order. -; "auto" detect order is changed according to mbstring.language -; http://php.net/mbstring.detect-order -;mbstring.detect_order = auto - -; substitute_character used when character cannot be converted -; one from another -; http://php.net/mbstring.substitute-character -;mbstring.substitute_character = none - -; overload(replace) single byte functions by mbstring functions. -; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), -; etc. Possible values are 0,1,2,4 or combination of them. -; For example, 7 for overload everything. -; 0: No overload -; 1: Overload mail() function -; 2: Overload str*() functions -; 4: Overload ereg*() functions -; http://php.net/mbstring.func-overload -;mbstring.func_overload = 0 - -; enable strict encoding detection. -; Default: Off -;mbstring.strict_detection = On - -; This directive specifies the regex pattern of content types for which mb_output_handler() -; is activated. -; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) -;mbstring.http_output_conv_mimetype= - -; This directive specifies maximum stack depth for mbstring regular expressions. It is similar -; to the pcre.recursion_limit for PCRE. -; Default: 100000 -;mbstring.regex_stack_limit=100000 - -[gd] -; Tell the jpeg decode to ignore warnings and try to create -; a gd image. The warning will then be displayed as notices -; disabled by default -; http://php.net/gd.jpeg-ignore-warning -;gd.jpeg_ignore_warning = 1 - -[exif] -; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. -; With mbstring support this will automatically be converted into the encoding -; given by corresponding encode setting. When empty mbstring.internal_encoding -; is used. For the decode settings you can distinguish between motorola and -; intel byte order. A decode setting cannot be empty. -; http://php.net/exif.encode-unicode -;exif.encode_unicode = ISO-8859-15 - -; http://php.net/exif.decode-unicode-motorola -;exif.decode_unicode_motorola = UCS-2BE - -; http://php.net/exif.decode-unicode-intel -;exif.decode_unicode_intel = UCS-2LE - -; http://php.net/exif.encode-jis -;exif.encode_jis = - -; http://php.net/exif.decode-jis-motorola -;exif.decode_jis_motorola = JIS - -; http://php.net/exif.decode-jis-intel -;exif.decode_jis_intel = JIS - -[Tidy] -; The path to a default tidy configuration file to use when using tidy -; http://php.net/tidy.default-config -;tidy.default_config = /usr/local/lib/php/default.tcfg - -; Should tidy clean and repair output automatically? -; WARNING: Do not use this option if you are generating non-html content -; such as dynamic images -; http://php.net/tidy.clean-output -tidy.clean_output = Off - -[soap] -; Enables or disables WSDL caching feature. -; http://php.net/soap.wsdl-cache-enabled -soap.wsdl_cache_enabled=1 - -; Sets the directory name where SOAP extension will put cache files. -; http://php.net/soap.wsdl-cache-dir -soap.wsdl_cache_dir="/tmp" - -; (time to live) Sets the number of second while cached file will be used -; instead of original one. -; http://php.net/soap.wsdl-cache-ttl -soap.wsdl_cache_ttl=86400 - -; Sets the size of the cache limit. (Max. number of WSDL files to cache) -soap.wsdl_cache_limit = 5 - -[sysvshm] -; A default size of the shared memory segment -;sysvshm.init_mem = 10000 - -[ldap] -; Sets the maximum number of open links or -1 for unlimited. -ldap.max_links = -1 - -[dba] -;dba.default_handler= - -[opcache] -; Determines if Zend OPCache is enabled -;opcache.enable=1 - -; Determines if Zend OPCache is enabled for the CLI version of PHP -;opcache.enable_cli=0 - -; The OPcache shared memory storage size. -;opcache.memory_consumption=128 - -; The amount of memory for interned strings in Mbytes. -;opcache.interned_strings_buffer=8 - -; The maximum number of keys (scripts) in the OPcache hash table. -; Only numbers between 200 and 1000000 are allowed. -;opcache.max_accelerated_files=10000 - -; The maximum percentage of "wasted" memory until a restart is scheduled. -;opcache.max_wasted_percentage=5 - -; When this directive is enabled, the OPcache appends the current working -; directory to the script key, thus eliminating possible collisions between -; files with the same name (basename). Disabling the directive improves -; performance, but may break existing applications. -;opcache.use_cwd=1 - -; When disabled, you must reset the OPcache manually or restart the -; webserver for changes to the filesystem to take effect. -;opcache.validate_timestamps=1 - -; How often (in seconds) to check file timestamps for changes to the shared -; memory storage allocation. ("1" means validate once per second, but only -; once per request. "0" means always validate) -;opcache.revalidate_freq=2 - -; Enables or disables file search in include_path optimization -;opcache.revalidate_path=0 - -; If disabled, all PHPDoc comments are dropped from the code to reduce the -; size of the optimized code. -;opcache.save_comments=1 - -; Allow file existence override (file_exists, etc.) performance feature. -;opcache.enable_file_override=0 - -; A bitmask, where each bit enables or disables the appropriate OPcache -; passes -;opcache.optimization_level=0x7FFFBFFF - -;opcache.dups_fix=0 - -; The location of the OPcache blacklist file (wildcards allowed). -; Each OPcache blacklist file is a text file that holds the names of files -; that should not be accelerated. The file format is to add each filename -; to a new line. The filename may be a full path or just a file prefix -; (i.e., /var/www/x blacklists all the files and directories in /var/www -; that start with 'x'). Line starting with a ; are ignored (comments). -;opcache.blacklist_filename= - -; Allows exclusion of large files from being cached. By default all files -; are cached. -;opcache.max_file_size=0 - -; Check the cache checksum each N requests. -; The default value of "0" means that the checks are disabled. -;opcache.consistency_checks=0 - -; How long to wait (in seconds) for a scheduled restart to begin if the cache -; is not being accessed. -;opcache.force_restart_timeout=180 - -; OPcache error_log file name. Empty string assumes "stderr". -;opcache.error_log= - -; All OPcache errors go to the Web server log. -; By default, only fatal errors (level 0) or errors (level 1) are logged. -; You can also enable warnings (level 2), info messages (level 3) or -; debug messages (level 4). -;opcache.log_verbosity_level=1 - -; Preferred Shared Memory back-end. Leave empty and let the system decide. -;opcache.preferred_memory_model= - -; Protect the shared memory from unexpected writing during script execution. -; Useful for internal debugging only. -;opcache.protect_memory=0 - -; Allows calling OPcache API functions only from PHP scripts which path is -; started from specified string. The default "" means no restriction -;opcache.restrict_api= - -; Mapping base of shared memory segments (for Windows only). All the PHP -; processes have to map shared memory into the same address space. This -; directive allows to manually fix the "Unable to reattach to base address" -; errors. -;opcache.mmap_base= - -; Enables and sets the second level cache directory. -; It should improve performance when SHM memory is full, at server restart or -; SHM reset. The default "" disables file based caching. -;opcache.file_cache= - -; Enables or disables opcode caching in shared memory. -;opcache.file_cache_only=0 - -; Enables or disables checksum validation when script loaded from file cache. -;opcache.file_cache_consistency_checks=1 - -; Implies opcache.file_cache_only=1 for a certain process that failed to -; reattach to the shared memory (for Windows only). Explicitly enabled file -; cache is required. -;opcache.file_cache_fallback=1 - -; Enables or disables copying of PHP code (text segment) into HUGE PAGES. -; This should improve performance, but requires appropriate OS configuration. -;opcache.huge_code_pages=1 - -; Validate cached file permissions. -;opcache.validate_permission=0 - -; Prevent name collisions in chroot'ed environment. -;opcache.validate_root=0 - -; If specified, it produces opcode dumps for debugging different stages of -; optimizations. -;opcache.opt_debug_level=0 - -[curl] -; A default value for the CURLOPT_CAINFO option. This is required to be an -; absolute path. -;curl.cainfo = - -[openssl] -; The location of a Certificate Authority (CA) file on the local filesystem -; to use when verifying the identity of SSL/TLS peers. Most users should -; not specify a value for this directive as PHP will attempt to use the -; OS-managed cert stores in its absence. If specified, this value may still -; be overridden on a per-stream basis via the "cafile" SSL stream context -; option. -;openssl.cafile= - -; If openssl.cafile is not specified or if the CA file is not found, the -; directory pointed to by openssl.capath is searched for a suitable -; certificate. This value must be a correctly hashed certificate directory. -; Most users should not specify a value for this directive as PHP will -; attempt to use the OS-managed cert stores in its absence. If specified, -; this value may still be overridden on a per-stream basis via the "capath" -; SSL stream context option. -;openssl.capath= - -; Local Variables: -; tab-width: 4 -; End: diff --git a/src/benchmarks/httpd/html/index.html b/src/benchmarks/httpd/html/index.html deleted file mode 100644 index 7052ab3..0000000 --- a/src/benchmarks/httpd/html/index.html +++ /dev/null @@ -1,5 +0,0 @@ -<html> -<body> -foobar -</body> -</html> diff --git a/src/benchmarks/httpd/html/index.php b/src/benchmarks/httpd/html/index.php deleted file mode 100644 index 0dde14e..0000000 --- a/src/benchmarks/httpd/html/index.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -// Show all information, defaults to INFO_ALL -phpinfo(); - -// Show just the module information. -// phpinfo(8) yields identical results. -phpinfo(INFO_MODULES); - -?> diff --git a/src/benchmarks/httpd/php/index.php b/src/benchmarks/httpd/php/index.php deleted file mode 100644 index 147cebc..0000000 --- a/src/benchmarks/httpd/php/index.php +++ /dev/null @@ -1 +0,0 @@ -<?php phpinfo(); ?> diff --git a/src/benchmarks/keydb.py b/src/benchmarks/keydb.py deleted file mode 100644 index 92470b0..0000000 --- a/src/benchmarks/keydb.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the keydb, a multi-threaded redis fork benchmark - - -This benchmark uses the memtier benchmark tool. -""" - -import os -import sys -from multiprocessing import cpu_count - -from src.artifact import GitArtifact -from src.benchmark import Benchmark -import src.plots as plt -from src.util import print_info, run_cmd - - -class BenchmarkKeyDB(Benchmark): - """Definition of the keydb benchmark""" - def __init__(self): - name = "keydb" - - self.cmd = "memtier_benchmark –hide-histogram --threads {threads} –data-size {size}" - self.args = {"threads": Benchmark.scale_threads_for_cpus(1 / 2), - "size": [8, 64, 256, 1024, 4096, 16384]} - - self.servers = [{ - "name": "keydb", - "cmd": f"keydb-server --server-threads 4", # 4 is the by keydb recommended amount - "shutdown_cmds": ["{build_dir}/keydb-cli shutdown"] - }] - - super().__init__(name) - - def prepare(self): - super().prepare() - - - keydb_version = "v5.3.1" - self.results["facts"]["versions"]["keydb"] = keydb_version - keydb_dir = os.path.join(self.build_dir, "keydb") - - if not os.path.exists(os.path.join(self.build_dir, "keydb-server")): - keydb = GitArtifact("keydb", "https://github.com/JohnSully/KeyDB") - - os.makedirs(self.build_dir, exist_ok=True) - - # checkout sources - keydb.provide(keydb_version, keydb_dir) - - # building keyDB - run_cmd(["make", "-C", keydb_dir, "MALLOC=libc"]) - - # create symlinks - for exe in ["keydb-cli", "keydb-server"]: - src = os.path.join(keydb_dir, "src", exe) - dest = os.path.join(self.build_dir, exe) - if not os.path.exists(dest): - os.link(src, dest) - - memtier_version = "1.2.17" - self.results["facts"]["versions"]["memtier"] = memtier_version - memtier_dir = os.path.join(self.build_dir, "memtier") - - if not os.path.exists(os.path.join(self.build_dir, "memtier_benchmark")): - memtier = GitArtifact("memtier", "https://github.com/RedisLabs/memtier_benchmark") - - memtier.provide(memtier_version, memtier_dir) - - # building memtier - run_cmd(["autoreconf", "-ivf"], cwd=memtier_dir) - run_cmd(["./configure"], cwd=memtier_dir) - run_cmd(["make"], cwd=memtier_dir) - - src = os.path.join(memtier_dir, "memtier_benchmark") - dest = os.path.join(self.build_dir, "memtier_benchmark") - if not os.path.exists(dest): - os.link(src, dest) - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - cmds = ["Sets", "Gets", "Waits", "Totals"] - stats = ["ops", "hits", "misses", "latency", "throughput"] - for line in stdout.splitlines(): - line = line.split() - if line and line[0] in cmds: - for i, stat in enumerate(stats): - result[f"{line[0].lower()}_{stat}"] = line[i + 1] - if result[f"{line[0].lower()}_{stat}"] == "---": - result[f"{line[0].lower()}_{stat}"] = "nan" - - @staticmethod - def cleanup(): - if os.path.exists("dump.rdb"): - os.remove("dump.rdb") - - def summary(self): - plt.plot(self, - "{totals_ops}", - fig_options={ - 'ylabel': "'OPS/second'", - 'title': "KeyDB Operations - {fixed_part_str}", - }, - file_postfix="total_ops") - - plt.plot(self, - "{keydb_vmhwm}", - fig_options={ - 'ylabel': "'VmHWM [KB]'", - 'title': "KeyDB Memusage - {fixed_part_str}", - }, - file_postfix="vmhwm") - -keydb = BenchmarkKeyDB() diff --git a/src/benchmarks/larson.py b/src/benchmarks/larson.py deleted file mode 100644 index db38789..0000000 --- a/src/benchmarks/larson.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Larson server benchmark - -This benchmark was build by Paul Larson at Microsoft Research. It -simulates a server: each thread has a set of allocations. From which it selects -a random slot. The allocation in this slot is freed, a new one with a random size -allocated, written to and stored in the selected slot. When a thread finished its -allocations it will pass its objects to a new thread. - -Larson benchmark usage: ./larson sleep min-size max-size chunks malloc_frees seed threads - -In the paper "Memory Allocation for Long-Running Server Applications" the authors -use 1000 chunks per thread and 50000 malloc and free pairs per thread which -correspond to a "bleeding rate" of 2% which they observed in real world systems. -The allocations are uniformly distributed between min-size and max-size. - -allocbench runs larson with different distributions and thread counts. -The other arguments are the same as the original authors used in their paper. - -mimalloc-bench uses 1000 chunks per thread and 10000 malloc and free pairs -simulating 10% bleeding. I don't know why they use different values than the -original paper. - - -Interpretation: - -This benchmark is intended to model a real world server workload. -But the use of a uniformly distribution of allocation sizes clearly differs from -real applications. Although the results can be a metric of scalability and -false sharing because it uses multiple threads, which pass memory around. -""" - -import re - -from src.benchmark import Benchmark -import src.plots as plt - -THROUGHPUT_RE = re.compile( - "^Throughput =\\s*(?P<throughput>\\d+) operations per second.$") - - -class BenchmarkLarson(Benchmark): - """Definition of the larson benchmark""" - def __init__(self): - name = "larson" - - # Parameters taken from the paper "Memory Allocation for Long-Running Server - # Applications" from Larson and Krishnan - self.cmd = "larson{binary_suffix} 5 8 {maxsize} 1000 50000 1 {threads}" - - self.args = { - "maxsize": [64, 512, 1024], - "threads": Benchmark.scale_threads_for_cpus(2) - } - - self.requirements = ["larson"] - super().__init__(name) - - @staticmethod - def process_output(result, stdout, stderr, target, perm): - for line in stdout.splitlines(): - res = THROUGHPUT_RE.match(line) - if res: - result["throughput"] = int(res.group("throughput")) - return - - def summary(self): - # Plot threads->throughput and maxsize->throughput - plt.plot(self, - "{throughput}/1000000", - fig_options={ - 'ylabel': "MOPS/s", - 'title': "Larson: {arg} {arg_value}", - }, - file_postfix="throughput") - - plt.plot(self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - fig_options={ - 'ylabel': "l1 cache misses in %", - 'title': "Larson cache misses: {arg} {arg_value}", - }, - file_postfix="cachemisses") - - -larson = BenchmarkLarson() diff --git a/src/benchmarks/larson/Makefile b/src/benchmarks/larson/Makefile deleted file mode 100644 index 0bb9a5b..0000000 --- a/src/benchmarks/larson/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CXX ?= g++ - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -OPTFLAGS ?= -O3 -DNDEBUG - -CXXFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDXXFLAGS ?= -pthread -static-libgcc -static-libstdc++ - -.PHONY: all clean - -all: $(OBJDIR)/larson - -$(OBJDIR)/larson: larson.cc | $(OBJDIR) - @echo compiling $@... - $(CXX) $(LDXXFLAGS) $(CXXFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/larson/larson.cc b/src/benchmarks/larson/larson.cc deleted file mode 100644 index 09bd885..0000000 --- a/src/benchmarks/larson/larson.cc +++ /dev/null @@ -1,754 +0,0 @@ -#include <assert.h> -#include <stdio.h> - -#if defined(_WIN32) -#define __WIN32__ -#endif - -#ifdef __WIN32__ -#include <windows.h> -#include <conio.h> -#include <process.h> - -#else -#include <unistd.h> -#include <sys/resource.h> -#include <sys/time.h> - -#ifndef __SVR4 -//extern "C" int pthread_setconcurrency (int) throw(); -#include <pthread.h> -#endif - - -typedef void * LPVOID; -typedef long long LONGLONG; -typedef long DWORD; -typedef long LONG; -typedef unsigned long ULONG; -typedef union _LARGE_INTEGER { - struct { - DWORD LowPart; - LONG HighPart; - } foo; - LONGLONG QuadPart; // In Visual C++, a typedef to _ _int64} LARGE_INTEGER; -} LARGE_INTEGER; -typedef long long _int64; -#ifndef TRUE -enum { TRUE = 1, FALSE = 0 }; -#endif -#include <assert.h> -#define _ASSERTE(x) assert(x) -#define _inline inline -void Sleep (long x) -{ - // printf ("sleeping for %ld seconds.\n", x/1000); - sleep(x/1000); -} - -void QueryPerformanceCounter (long * x) -{ - struct timezone tz; - struct timeval tv; - gettimeofday (&tv, &tz); - *x = tv.tv_sec * 1000000L + tv.tv_usec; -} - -void QueryPerformanceFrequency(long * x) -{ - *x = 1000000L; -} - - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <ctype.h> -#include <time.h> -#include <assert.h> - -#define _REENTRANT 1 -#include <pthread.h> -#ifdef __sun -#include <thread.h> -#endif -typedef void * VoidFunction (void *); -void _beginthread (VoidFunction x, int, void * z) -{ - pthread_t pt; - pthread_attr_t pa; - pthread_attr_init (&pa); - -#if 1//defined(__SVR4) - pthread_attr_setscope (&pa, PTHREAD_SCOPE_SYSTEM); /* bound behavior */ -#endif - - // printf ("creating a thread.\n"); - int v = pthread_create(&pt, &pa, x, z); - // printf ("v = %d\n", v); -} -#endif - - -#if 0 -static char buf[65536]; - -#define malloc(v) &buf -#define free(p) -#endif - -#undef CPP -//#define CPP -//#include "arch-specific.h" - -#if USE_ROCKALL -//#include "FastHeap.hpp" -//FAST_HEAP theFastHeap (1024 * 1024, true, true, true); - -typedef int SBIT32; - -#include "SmpHeap.hpp" -SMP_HEAP theFastHeap (1024 * 1024, true, true, true); - -void * operator new( unsigned int cb ) -{ - void *pRet = theFastHeap.New ((size_t)cb) ; - return pRet; -} - -void operator delete[](void *pUserData ) -{ - theFastHeap.Delete (pUserData) ; -} -#endif - -#if 0 -extern "C" void * hdmalloc (size_t sz) ; -extern "C" void hdfree (void * ptr) ; -extern "C" void hdmalloc_stats (void) ; -void * operator new( unsigned int cb ) -{ - void *pRet = hdmalloc((size_t)cb) ; - return pRet; -} - -void operator delete[](void *pUserData ) -{ - hdfree(pUserData) ; -} -#endif - - - -/* Test driver for memory allocators */ -/* Author: Paul Larson, palarson@microsoft.com */ -#define MAX_THREADS 100 -#define MAX_BLOCKS 20000000 - -int volatile stopflag=FALSE ; - -struct lran2_st { - long x, y, v[97]; -}; - -int TotalAllocs=0 ; - -typedef struct thr_data { - - int threadno ; - int NumBlocks ; - int seed ; - - int min_size ; - int max_size ; - - char * *array ; - int *blksize ; - int asize ; - - unsigned long cAllocs ; - unsigned long cFrees ; - int cThreads ; - unsigned long cBytesAlloced ; - - pthread_barrier_t *barrier; - - volatile int finished ; - struct lran2_st rgen ; - -} thread_data; - -void runthreads(long sleep_cnt, int min_threads, int max_threads, - int chperthread, int num_rounds) ; -void runloops(long sleep_cnt, int num_chunks ) ; -static void warmup(char **blkp, int num_chunks ); -static void * exercise_heap( void *pinput) ; -static void lran2_init(struct lran2_st* d, long seed) ; -static long lran2(struct lran2_st* d) ; -ULONG CountReservedSpace() ; - -char ** blkp = new char *[MAX_BLOCKS] ; -int * blksize = new int[MAX_BLOCKS] ; -long seqlock=0 ; -struct lran2_st rgen ; -int min_size=10, max_size=500 ; -int num_threads ; -ULONG init_space ; - -extern int cLockSleeps ; -extern int cAllocedChunks ; -extern int cAllocedSpace ; -extern int cUsedSpace ; -extern int cFreeChunks ; -extern int cFreeSpace ; - -int cChecked=0 ; - -#if defined(_WIN32) -extern "C" { - extern HANDLE crtheap; -}; -#endif - -int main (int argc, char *argv[]) -{ -#if defined(USE_LFH) && defined(_WIN32) - // Activate 'Low Fragmentation Heap'. - ULONG info = 2; - HeapSetInformation (GetProcessHeap(), - HeapCompatibilityInformation, - &info, - sizeof(info)); -#endif -#if 0 // defined(__SVR4) - { - psinfo_t ps; - int pid = getpid(); - char fname[255]; - sprintf (fname, "/proc/%d/psinfo", pid); - // sprintf (fname, "/proc/self/ps"); - FILE * f = fopen (fname, "rb"); - printf ("opening %s\n", fname); - if (f) { - fread (&ps, sizeof(ps), 1, f); - printf ("resident set size = %dK\n", ps.pr_rssize); - fclose (f); - } - } -#endif - -#if defined(_MT) || defined(_REENTRANT) - int min_threads, max_threads ; - int num_rounds ; - int chperthread ; -#endif - unsigned seed=12345 ; - int num_chunks=10000; - long sleep_cnt; - - if (argc > 7) { - sleep_cnt = atoi(argv[1]); - min_size = atoi(argv[2]); - max_size = atoi(argv[3]); - chperthread = atoi(argv[4]); - num_rounds = atoi(argv[5]); - seed = atoi(argv[6]); - max_threads = atoi(argv[7]); - min_threads = max_threads; - printf ("sleep = %ld, min = %d, max = %d, per thread = %d, num rounds = %d, seed = %d, max_threads = %d, min_threads = %d\n", - sleep_cnt, min_size, max_size, chperthread, num_rounds, seed, max_threads, min_threads); - goto DoneWithInput; - } - -#if defined(_MT) || defined(_REENTRANT) - //#ifdef _MT - printf( "\nMulti-threaded test driver \n") ; -#else - printf( "\nSingle-threaded test driver \n") ; -#endif -#ifdef CPP - printf("C++ version (new and delete)\n") ; -#else - printf("C version (malloc and free)\n") ; -#endif - printf("runtime (sec): ") ; - scanf ("%ld", &sleep_cnt); - - printf("chunk size (min,max): ") ; - scanf("%d %d", &min_size, &max_size ) ; -#if defined(_MT) || defined(_REENTRANT) - //#ifdef _MT - printf("threads (min, max): ") ; - scanf("%d %d", &min_threads, &max_threads) ; - printf("chunks/thread: ") ; scanf("%d", &chperthread ) ; - printf("no of rounds: ") ; scanf("%d", &num_rounds ) ; - num_chunks = max_threads*chperthread ; -#else - printf("no of chunks: ") ; scanf("%d", &num_chunks ) ; -#endif - printf("random seed: ") ; scanf("%d", &seed) ; - - DoneWithInput: - - if( num_chunks > MAX_BLOCKS ){ - printf("Max %d chunks - exiting\n", MAX_BLOCKS ) ; - return(1) ; - } - -#ifndef __WIN32__ -#ifdef __SVR4 - pthread_setconcurrency (max_threads); -#endif -#endif - - lran2_init(&rgen, seed) ; - // init_space = CountReservedSpace() ; - -#if defined(_MT) || defined(_REENTRANT) - //#ifdef _MT - runthreads(sleep_cnt, min_threads, max_threads, chperthread, num_rounds) ; -#else - runloops(sleep_cnt, num_chunks ) ; -#endif - -#ifdef _DEBUG - _cputs("Hit any key to exit...") ; (void)_getch() ; -#endif - - return 0; - -} /* main */ - -void runloops(long sleep_cnt, int num_chunks ) -{ - int cblks ; - int victim ; - int blk_size ; -#ifdef __WIN32__ - _LARGE_INTEGER ticks_per_sec, start_cnt, end_cnt; -#else - long ticks_per_sec ; - long start_cnt, end_cnt ; -#endif - _int64 ticks ; - double duration ; - double reqd_space ; - ULONG used_space ; - int sum_allocs=0 ; - - QueryPerformanceFrequency( &ticks_per_sec ) ; - QueryPerformanceCounter( &start_cnt) ; - - for( cblks=0; cblks<num_chunks; cblks++){ - if (max_size == min_size) { - blk_size = min_size; - } else { - blk_size = min_size+lran2(&rgen)%(max_size - min_size) ; - } -#ifdef CPP - blkp[cblks] = new char[blk_size] ; -#else - blkp[cblks] = (char *) malloc(blk_size) ; -#endif - blksize[cblks] = blk_size ; - assert(blkp[cblks] != NULL) ; - } - - while(TRUE){ - for( cblks=0; cblks<num_chunks; cblks++){ - victim = lran2(&rgen)%num_chunks ; -#ifdef CPP - delete[] blkp[victim] ; -#else - free(blkp[victim]) ; -#endif - - if (max_size == min_size) { - blk_size = min_size; - } else { - blk_size = min_size+lran2(&rgen)%(max_size - min_size) ; - } -#ifdef CPP - blkp[victim] = new char[blk_size] ; -#else - blkp[victim] = (char *) malloc(blk_size) ; -#endif - blksize[victim] = blk_size ; - assert(blkp[victim] != NULL) ; - } - sum_allocs += num_chunks ; - - QueryPerformanceCounter( &end_cnt) ; -#ifdef __WIN32__ - ticks = end_cnt.QuadPart - start_cnt.QuadPart ; - duration = (double)ticks/ticks_per_sec.QuadPart ; -#else - ticks = end_cnt - start_cnt ; - duration = (double)ticks/ticks_per_sec ; -#endif - - if( duration >= sleep_cnt) break ; - } - reqd_space = (0.5*(min_size+max_size)*num_chunks) ; - // used_space = CountReservedSpace() - init_space; - - printf("%6.3f", duration ) ; - printf("%8.0f", sum_allocs/duration ) ; - printf(" %6.3f %.3f", (double)used_space/(1024*1024), used_space/reqd_space) ; - printf("\n") ; - -} - - -#if defined(_MT) || defined(_REENTRANT) -//#ifdef _MT -void runthreads(long sleep_cnt, int min_threads, int max_threads, int chperthread, int num_rounds) -{ - thread_data *de_area = new thread_data[max_threads] ; - thread_data *pdea; - int nperthread ; - int sum_threads ; - unsigned long sum_allocs ; - unsigned long sum_frees ; - double duration ; -#ifdef __WIN32__ - _LARGE_INTEGER ticks_per_sec, start_cnt, end_cnt; -#else - long ticks_per_sec ; - long start_cnt, end_cnt ; -#endif - _int64 ticks ; - double rate_1=0, rate_n ; - double reqd_space ; - ULONG used_space ; - int prevthreads ; - int i ; - - QueryPerformanceFrequency( &ticks_per_sec ) ; - - pdea = &de_area[0] ; - memset(&de_area[0], 0, sizeof(thread_data)) ; - - prevthreads = 0 ; - for(num_threads=min_threads; num_threads <= max_threads; num_threads++ ) - { - - warmup(&blkp[prevthreads*chperthread], (num_threads-prevthreads)*chperthread ); - - nperthread = chperthread ; - stopflag = FALSE ; - - pthread_barrier_t barrier; - pthread_barrier_init(&barrier, NULL, num_threads + 1); - - for(i=0; i< num_threads; i++){ - de_area[i].threadno = i+1 ; - de_area[i].NumBlocks = num_rounds*nperthread; - de_area[i].array = &blkp[i*nperthread] ; - de_area[i].blksize = &blksize[i*nperthread] ; - de_area[i].asize = nperthread ; - de_area[i].min_size = min_size ; - de_area[i].max_size = max_size ; - de_area[i].seed = lran2(&rgen) ; ; - de_area[i].finished = 0 ; - de_area[i].cAllocs = 0 ; - de_area[i].cFrees = 0 ; - de_area[i].cThreads = 0 ; - de_area[i].barrier = &barrier ; - de_area[i].finished = FALSE ; - lran2_init(&de_area[i].rgen, de_area[i].seed) ; - -#ifdef __WIN32__ - _beginthread((void (__cdecl*)(void *)) exercise_heap, 0, &de_area[i]) ; -#else - _beginthread(exercise_heap, 0, &de_area[i]) ; -#endif - - } - - pthread_barrier_wait(&barrier); - - QueryPerformanceCounter( &start_cnt) ; - - // printf ("Sleeping for %ld seconds.\n", sleep_cnt); - Sleep(sleep_cnt * 1000L) ; - - stopflag = TRUE ; - - for(i=0; i<num_threads; i++){ - while( !de_area[i].finished ){ -#ifdef __WIN32__ - Sleep(1); -#elif defined(__SVR4) - thr_yield(); -#else - sched_yield(); -#endif - } - } - - - QueryPerformanceCounter( &end_cnt) ; - - sum_frees = sum_allocs =0 ; - sum_threads = 0 ; - for(i=0;i< num_threads; i++){ - sum_allocs += de_area[i].cAllocs ; - sum_frees += de_area[i].cFrees ; - sum_threads += de_area[i].cThreads ; - de_area[i].cAllocs = de_area[i].cFrees = 0; - } - - -#ifdef __WIN32__ - ticks = end_cnt.QuadPart - start_cnt.QuadPart ; - duration = (double)ticks/ticks_per_sec.QuadPart ; -#else - ticks = end_cnt - start_cnt ; - duration = (double)ticks/ticks_per_sec ; -#endif - - for( i=0; i<num_threads; i++){ - if( !de_area[i].finished ) - printf("Thread at %d not finished\n", i) ; - } - - - rate_n = sum_allocs/duration ; - if( rate_1 == 0){ - rate_1 = rate_n ; - } - - reqd_space = (0.5*(min_size+max_size)*num_threads*chperthread) ; - // used_space = CountReservedSpace() - init_space; - used_space = 0; - - printf ("Throughput = %8.0f operations per second.\n", sum_allocs / duration); - -#if 0 - printf("%2d ", num_threads ) ; - printf("%6.3f", duration ) ; - printf("%6.3f", rate_n/rate_1 ) ; - printf("%8.0f", sum_allocs/duration ) ; - printf(" %6.3f %.3f", (double)used_space/(1024*1024), used_space/reqd_space) ; - printf("\n") ; -#endif - - Sleep(5000L) ; // wait 5 sec for old threads to die - - prevthreads = num_threads ; - - printf ("Done sleeping...\n"); - - } - delete [] de_area; -} - - -static void * exercise_heap( void *pinput) -{ - thread_data *pdea; - int cblks=0 ; - int victim ; - long blk_size ; - int range ; - - if( stopflag ) return 0; - - pdea = (thread_data *)pinput ; - pdea->finished = FALSE ; - pdea->cThreads++ ; - range = pdea->max_size - pdea->min_size ; - - pthread_barrier_wait(pdea->barrier); - - /* allocate NumBlocks chunks of random size */ - for( cblks=0; cblks<pdea->NumBlocks; cblks++){ - victim = lran2(&pdea->rgen)%pdea->asize ; -#ifdef CPP - delete[] pdea->array[victim] ; -#else - free(pdea->array[victim]) ; -#endif - pdea->cFrees++ ; - - if (range == 0) { - blk_size = pdea->min_size; - } else { - blk_size = pdea->min_size+lran2(&pdea->rgen)%range ; - } -#ifdef CPP - pdea->array[victim] = new char[blk_size] ; -#else - pdea->array[victim] = (char *) malloc(blk_size) ; -#endif - - pdea->blksize[victim] = blk_size ; - assert(pdea->array[victim] != NULL) ; - - pdea->cAllocs++ ; - - /* Write something! */ - - volatile char * chptr = ((char *) pdea->array[victim]); - *chptr++ = 'a'; - volatile char ch = *((char *) pdea->array[victim]); - *chptr = 'b'; - - - if( stopflag ) break ; - } - - // printf("Thread %u terminating: %d allocs, %d frees\n", - // pdea->threadno, pdea->cAllocs, pdea->cFrees) ; - pdea->finished = TRUE ; - - if( !stopflag ){ -#ifdef __WIN32__ - _beginthread((void (__cdecl*)(void *)) exercise_heap, 0, pdea) ; -#else - _beginthread(exercise_heap, 0, pdea) ; -#endif - } else { - printf ("thread stopping.\n"); - } -#ifndef _WIN32 - pthread_exit (NULL); -#endif - return 0; -} - -static void warmup(char **blkp, int num_chunks ) -{ - int cblks ; - int victim ; - int blk_size ; - LPVOID tmp ; - - - for( cblks=0; cblks<num_chunks; cblks++){ - if (min_size == max_size) { - blk_size = min_size; - } else { - blk_size = min_size+lran2(&rgen)%(max_size-min_size) ; - } -#ifdef CPP - blkp[cblks] = new char[blk_size] ; -#else - blkp[cblks] = (char *) malloc(blk_size) ; -#endif - blksize[cblks] = blk_size ; - assert(blkp[cblks] != NULL) ; - } - - /* generate a random permutation of the chunks */ - for( cblks=num_chunks; cblks > 0 ; cblks--){ - victim = lran2(&rgen)%cblks ; - tmp = blkp[victim] ; - blkp[victim] = blkp[cblks-1] ; - blkp[cblks-1] = (char *) tmp ; - } - - for( cblks=0; cblks<4*num_chunks; cblks++){ - victim = lran2(&rgen)%num_chunks ; -#ifdef CPP - delete[] blkp[victim] ; -#else - free(blkp[victim]) ; -#endif - - if (max_size == min_size) { - blk_size = min_size; - } else { - blk_size = min_size+lran2(&rgen)%(max_size - min_size) ; - } -#ifdef CPP - blkp[victim] = new char[blk_size] ; -#else - blkp[victim] = (char *) malloc(blk_size) ; -#endif - blksize[victim] = blk_size ; - assert(blkp[victim] != NULL) ; - } -} -#endif // _MT - -#ifdef __WIN32__ -ULONG CountReservedSpace() -{ - MEMORY_BASIC_INFORMATION info; - char *addr=NULL ; - ULONG size=0 ; - - while( true){ - VirtualQuery(addr, &info, sizeof(info)); - switch( info.State){ - case MEM_FREE: - case MEM_RESERVE: - break ; - case MEM_COMMIT: - size += info.RegionSize ; - break ; - } - addr += info.RegionSize ; - if( addr >= (char *)0x80000000UL ) break ; - } - - return size ; - -} -#endif - -// ======================================================= - -/* lran2.h - * by Wolfram Gloger 1996. - * - * A small, portable pseudo-random number generator. - */ - -#ifndef _LRAN2_H -#define _LRAN2_H - -#define LRAN2_MAX 714025l /* constants for portable */ -#define IA 1366l /* random number generator */ -#define IC 150889l /* (see e.g. `Numerical Recipes') */ - -//struct lran2_st { -// long x, y, v[97]; -//}; - -static void -lran2_init(struct lran2_st* d, long seed) -{ - long x; - int j; - - x = (IC - seed) % LRAN2_MAX; - if(x < 0) x = -x; - for(j=0; j<97; j++) { - x = (IA*x + IC) % LRAN2_MAX; - d->v[j] = x; - } - d->x = (IA*x + IC) % LRAN2_MAX; - d->y = d->x; -} - -static -long lran2(struct lran2_st* d) -{ - int j = (d->y % 97); - - d->y = d->v[j]; - d->x = (IA*d->x + IC) % LRAN2_MAX; - d->v[j] = d->x; - return d->y; -} - -#undef IA -#undef IC - -#endif - - diff --git a/src/benchmarks/lld.py b/src/benchmarks/lld.py deleted file mode 100644 index 55b9063..0000000 --- a/src/benchmarks/lld.py +++ /dev/null @@ -1,300 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""llvm-lld speed benchmark - -This benchmark runs the lld speed benchmark provided by the llvm project. -The archive contains compiled object files and linker instructions -for prominent software projects. -The benchmark starts lld in each project and measures lld's execution time. -Lld uses all available execution units. - -Included workloads are (allocator functions with call count < 100 are neglected): -Checksum: 2d449a11109c7363f67fd45513b42270f5ba2a92 -* chromium - * Version: 50.0.2638.0 - * allocator calls: 728968 - * malloc: 585155 (80%) - * free: 143660 (20%) - * Approximate allocator ratios: - * malloc: 1.33% - * free: 0.22% - * Top 10 allocation sizes 66.59% of all allocations - 1. 32 B occurred 96691 times - 2. 64 B occurred 84242 times - 3. 128 B occurred 51477 times - 4. 96 B occurred 36551 times - 5. 256 B occurred 29329 times - 6. 160 B occurred 22882 times - 7. 192 B occurred 20409 times - 8. 16 B occurred 16843 times - 9. 224 B occurred 15886 times - 10. 512 B occurred 15448 times - - allocations <= 64:› 217964› 37.24% - allocations <= 1024:› 542138› 92.62% - allocations <= 4096:› 572589› 97.83% - -* mozilla - * allocator calls: 565923 - * malloc: 446864 (79%) - * free: 118928 (21%) - * Approximate allocator ratios: - * malloc: 0.19% - * free: 0.07% - * Top 10 allocation sizes 86.56% of all allocations - 1. 32 B occurred 161545 times - 2. 64 B occurred 70863 times - 3. 24 B occurred 46400 times - 4. 40 B occurred 34304 times - 5. 96 B occurred 25742 times - 6. 128 B occurred 16993 times - 7. 160 B occurred 10670 times - 8. 256 B occurred 9157 times - 9. 192 B occurred 6357 times - 10. 224 B occurred 4878 times - - allocations <= 64: 317816 71.10% - allocations <= 1024: 419747 93.90% - allocations <= 4096: 430815 96.38% - -* linux kernel - * Linux version 4.14.0-rc1+ (fedora@ip-172-31-12-81.us-west-2.compute.internal) - (gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) #2 SMP Wed Sep 20 21:57:18 UTC 2017 - * allocator calls: 8607279 - * malloc: 4328149 (50%) - * free: 4279068 (50%) - * Approximate allocator ratios: - * malloc: 3.82% - * free: 6.03% - * Top 10 allocation sizes 77.95% of all allocations - 1. 57 B occurred 1420196 times - 2. 29 B occurred 1368747 times - 3. 50 B occurred 89909 times - 4. 48 B occurred 76702 times - 5. 56 B occurred 73398 times - 6. 55 B occurred 71073 times - 7. 51 B occurred 70718 times - 8. 53 B occurred 69945 times - 9. 49 B occurred 67552 times - 10. 52 B occurred 65639 times - - allocations <= 64: 4114410 95.06% - allocations <= 1024: 4320775 99.83% - allocations <= 4096: 4325016 99.93% - -* scylla - NoSQL data store https://github.com/scylladb/scylla - * allocator calls: 106968 - * malloc: 66984 (63%) - * free: 39884 (37%) - * Approximate allocator ratios: - * malloc: 0.06% - * free: 0.04% - * Top 10 allocation sizes 73.65% of all allocations - 1. 24 B occurred 18005 times - 2. 40 B occurred 13089 times - 3. 96 B occurred 3693 times - 4. 128 B occurred 3280 times - 5. 32 B occurred 2827 times - 6. 64 B occurred 2728 times - 7. 256 B occurred 1596 times - 8. 160 B occurred 1553 times - 9. 192 B occurred 1371 times - 10. 4096 B occurred 1268 times - - allocations <= 64: 38375 57.20% - allocations <= 1024: 59302 88.40% - allocations <= 4096: 63005 93.92% - -* llvm variants (as-fsds, as) - * allocator calls: 21074 | 23508 - * malloc: 61% | 58% - * free: 38% | 41% - * Approximate allocator ratios: - * malloc: 1.26% | 0.93% - * free: 1.13% | 0.69%) - * Top 10 allocation sizes 74.77% | Top 10 allocation sizes 82.64% of all allocations - 1. 24 B occurred 4453 times | 1. 24 B occurred 5742 times - 2. 40 B occurred 3067 times | 2. 40 B occurred 3908 times - 3. 4096 B occurred 581 times | 3. 4096 B occurred 535 times - 4. 32 B occurred 291 times | 4. 80 B occurred 240 times - 5. 8192 B occurred 260 times | 5. 64 B occurred 196 times - 6. 64 B occurred 252 times | 6. 32 B occurred 191 times - 7. 96 B occurred 233 times | 7. 8192 B occurred 189 times - 8. 80 B occurred 227 times | 8. 8 B occurred 180 times - 9. 128 B occurred 197 times | 9. 128 B occurred 163 times - 10. 256 B occurred 178 times | 10. 96 B occurred 159 times - - allocations <= 64: 8668 66.55% | allocations <= 64:>.10722>..77.03% - allocations <= 1024: 11646 89.41% | allocations <= 1024:>...12783>..91.83% - allocations <= 4096: 12597 96.71% | allocations <= 4096:>...13543>..97.29% - -* llvm gold LTO plugin (gold, gold-fsds) - * allocator calls: 66302 | 87841 - * malloc: 64% | 71% - * free: 35% | 29% - * Approximate allocator ratios: - * malloc: 0.69% | 1.02% - * free: 0.32% | 0.37% - * Top 10 allocation sizes 62.19% | Top 10 allocation sizes 57.24% - 1. 24 B occurred 7574 times | 1. 24 B occurred 9563 times - 2. 40 B occurred 5406 times | 2. 40 B occurred 6833 times - 3. 32 B occurred 2587 times | 3. 32 B occurred 3843 times - 4. 64 B occurred 2350 times | 4. 64 B occurred 3740 times - 5. 128 B occurred 2233 times | 5. 128 B occurred 2974 times - 6. 256 B occurred 1621 times | 6. 160 B occurred 2092 times - 7. 16 B occurred 1551 times | 7. 256 B occurred 2055 times - 8. 512 B occurred 1316 times | 8. 512 B occurred 1586 times - 9. 4096 B occurred 1198 times | 9. 96 B occurred 1579 times - 10. 160 B occurred 818 times | 10. 16 B occurred 1424 times - - allocations <= 64: 20501 47.83% | allocations <= 64: 26093 41.85% - allocations <= 1024: 37224 86.85% | allocations <= 1024: 53860 86.38% - allocations <= 4096: 40646 94.83% | allocations <= 4096: 59821 95.94% - -* clang (clang, clang-fsds, clang-gdb-index) - * allocator calls: 70378 | 111081 | 1271367 - * malloc: 70% | 81% | 59% - * free: 30% | 19% | 29% - * realloc: 0% | 0% | 11% - * Approximate allocator ratios: - * malloc: 0.68% | 0.95% | 0.82% - * free: 0.29% | 0.20% | 0.32% - * realloc: 0% | 0% | 0.10% - * Top 10 allocation sizes 52.99% | Top 10 allocation sizes 49.91% | Top 10 allocation sizes 83.46% - 1. 24 B occurred 7916 times | 1. 24 B occurred 8503 times | 1. 32 B occurred 205122 times - 2. 40 B occurred 5788 times | 2. 40 B occurred 6286 times | 2. 4 B occurred 127071 times - 3. 32 B occurred 2192 times | 3. 32 B occurred 5507 times | 3. 16 B occurred 110454 times - 4. 128 B occurred 1969 times | 4. 64 B occurred 5289 times | 4. 24 B occurred 61859 times - 5. 64 B occurred 1958 times | 5. 128 B occurred 4306 times | 5. 64 B occurred 58384 times - 6. 256 B occurred 1505 times | 6. 160 B occurred 3743 times | 6. 80 B occurred 53354 times - 7. 4096 B occurred 1318 times | 7. 96 B occurred 3319 times | 7. 40 B occurred 44931 times - 8. 160 B occurred 1305 times | 8. 256 B occurred 2762 times | 8. 8 B occurred 36572 times - 9. 320 B occurred 1140 times | 9. 192 B occurred 2592 times | 9. 96 B occurred 25162 times - 10. 512 B occurred 1099 times | 10. 320 B occurred 2433 times | 10. 160 B occurred 23729 times - - allocations <= 64: 19989 40.44% | allocations <= 64: 26994 30.11% | allocations <= 64: 649038 72.55% - allocations <= 1024: 41806 84.58% | allocations <= 1024: 75184 83.87% | allocations <= 1024: 847322 94.72% - allocations <= 4096: 46102 93.28% | allocations <= 4096: 85490 95.37% | allocations <= 4096: 871017 97.37% - -Interpretation: - -The raw speed of the allocator likewise is not a huge factor because of the small -small portion of the total execution time (around 1% except scylla and linux). -So data locality and scalability should be the most important factor for those workloads. -""" - -import os - -import matplotlib.pyplot as plt - -from src.artifact import ArchiveArtifact -from src.benchmark import Benchmark -import src.facter -import src.plots -from src.globalvars import summary_file_ext - - -class BenchmarkLld(Benchmark): - """LLVM-lld speed benchmark definition""" - def __init__(self): - name = "lld" - - self.run_dir = "{test_dir}/lld-speed-test/{test}" - # TODO: don't hardcode ld.lld location - self.cmd = "/usr/bin/ld.lld @response.txt" - - self.args = { - "test": [ - "chrome", "clang-fsds", "gold", "linux-kernel", "llvm-as-fsds", - "scylla", "clang", "clang-gdb-index", "gold-fsds", "llvm-as", - "mozilla" - ] - } - - self.measure_cmd = "perf stat -x, -d time -f %M,KB,VmHWM" - self.measure_cmd_csv = True - self.requirements = ["ld.lld"] - super().__init__(name) - - def prepare(self): - super().prepare() - - # save lld version - self.results["facts"]["versions"]["lld"] = src.facter.exe_version( - "ld.lld", "-v") - - tests = ArchiveArtifact( - "lld-speed-test", - "https://s3-us-west-2.amazonaws.com/linker-tests/lld-speed-test.tar.xz", - "tar", "2d449a11109c7363f67fd45513b42270f5ba2a92") - self.test_dir = tests.provide() - - def cleanup(self): - for perm in self.iterate_args(): - a_out = os.path.join(self.test_dir, "lld-speed-test", perm.test, - "a.out") - if os.path.isfile(a_out): - os.remove(a_out) - - def summary(self): - args = self.results["args"] - allocators = self.results["allocators"] - stats = self.results["stats"] - - for perm in self.iterate_args(args=args): - for i, allocator in enumerate(allocators): - - plt.bar([i], - stats[allocator][perm]["mean"]["task-clock"], - yerr=stats[allocator][perm]["std"]["task-clock"], - label=allocator, - color=allocators[allocator]["color"]) - - plt.legend(loc="best") - plt.ylabel("time in ms") - plt.title(f"Runtime {perm.test}") - plt.savefig(f"{self.name}.{perm.test}.runtime.{summary_file_ext}") - plt.clf() - - for i, alloc in enumerate(allocators): - plt.bar([i], - stats[alloc][perm]["mean"]["VmHWM"] / 1000, - yerr=stats[alloc][perm]["std"]["VmHWM"] / 1000, - label=alloc, - color=allocators[alloc]["color"]) - - plt.legend(loc="best") - plt.ylabel("Max RSS in MB") - plt.title(f"Max RSS {perm.test}") - plt.savefig(f"{self.name}.{perm.test}.rss.{summary_file_ext}") - plt.clf() - - # self.export_stats_to_csv("VmHWM") - src.plots.export_stats_to_csv(self, "task-clock") - - # self.export_stats_to_dataref("VmHWM") - src.plots.export_stats_to_dataref(self, "task-clock") - - src.plots.write_tex_table(self, [{ - "label": "Runtime [ms]", - "expression": "{task-clock}", - "sort": "<" - }], - file_postfix="table") - - -lld = BenchmarkLld() diff --git a/src/benchmarks/loop.py b/src/benchmarks/loop.py deleted file mode 100644 index 030552b..0000000 --- a/src/benchmarks/loop.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the loop micro benchmark - -This benchmark allocates and immediately deallocates a pseudo random sized allocation -N times in T threads. The acquired memory is neither read nor written. Not using the -allocations at all maybe seems odd but this micro benchmark should only measure -the allocators fast paths, scalability and management overhead. -Using the allocations will add cache effects to our results which are -measured for example in the false sharing or larson benchmarks. - -Observations: -* Glibc's factor two faster for allocations <= 1024B -* TCMalloc suffers when allocating only small chunks - -Interpretation: -* A significant higher cache miss rate than other allocators could mean that - internals suffer from false sharing (TCMalloc). -* Speed changes with constant threads but changing sizes may show performance - differences in differing strategies for seperate sizes (glibc thread caches < 1032B) -""" - -from src.benchmark import Benchmark -import src.plots as plt - - -class BenchmarkLoop(Benchmark): - """Loop micro benchmark - - This benchmark allocates and frees n blocks in t concurrent threads. - """ - def __init__(self): - name = "loop" - - self.cmd = "loop{binary_suffix} {threads} 1000000 {maxsize}" - - self.args = { - "maxsize": [2**x for x in range(6, 16)], - "threads": Benchmark.scale_threads_for_cpus(2) - } - - self.requirements = ["loop"] - super().__init__(name) - - def process_output(self, result, stdout, stderr, alloc, perm): - result["mops"] = perm.threads / float(result["task-clock"]) - - def summary(self): - # Speed - plt.plot( - self, - "{mops}", - fig_options={ - 'ylabel': 'MOPS/cpu-second', - 'title': 'Loop: {fixed_part_str}', - 'autoticks': False, - }, - file_postfix="time") - - # L1 cache misses - plt.plot( - self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - fig_options={ - 'ylabel': "L1 misses in %", - 'title': "Loop l1 cache misses: {fixed_part_str}", - 'autoticks': False, - }, - file_postfix="l1misses") - - # Speed Matrix - plt.write_best_doublearg_tex_table( - self, - "{mops}", - file_postfix="time.matrix") - - plt.write_tex_table( - self, - [{ - "label": "MOPS/s", - "expression": "{mops}", - "sort": ">" - }], - file_postfix="mops.table") - - plt.export_stats_to_csv(self, "task-clock") - plt.export_stats_to_dataref(self, "task-clock") - - # pgfplot test - plt.pgfplot(self, - self.iterate_args(fixed={"maxsize": 1024}, args=self.results["args"]), - "int(perm.threads)", - "{mops}", - xlabel="Threads", - ylabel="MOPS/cpu-second", - title="Loop: 1024B", - postfix='mops_1024B') - - # create pgfplot legend - plt.pgfplot_legend(self) - - -loop = BenchmarkLoop() diff --git a/src/benchmarks/loop/Makefile b/src/benchmarks/loop/Makefile deleted file mode 100644 index d9d64c2..0000000 --- a/src/benchmarks/loop/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -pthread -OPTFLAGS ?= -O0 -g - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -.PHONY = all clean - -all: $(OBJDIR)/loop - -$(OBJDIR)/loop: loop.c Makefile | $(OBJDIR) - @echo compiling $@... - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/loop/loop.c b/src/benchmarks/loop/loop.c deleted file mode 100644 index 04dcd80..0000000 --- a/src/benchmarks/loop/loop.c +++ /dev/null @@ -1,45 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int size, iterations; - -static void* test_thread_func(__attribute__ ((unused)) void* arg) { - for(int i = 0; i < iterations; i++) { - free(malloc(size)); - } - return NULL; -} - -int main(int argc, char* argv[]) { - pthread_t* threads; - int num_threads; - - if (argc != 4) { - fprintf(stderr, "Usage: %s <num threads> <iterations> <size>\n", argv[0]); - return 1; - } - - num_threads = atoi(argv[1]); - iterations = atoi(argv[2]); - size = atoi(argv[3]); - - threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t)); - - for (int i = 0; i < num_threads; i++) { - if (0 != pthread_create(&threads[i], NULL, test_thread_func, NULL)) { - perror("pthread_create"); - return 1; - } - } - - for(int i = 0; i < num_threads; i++) { - if (0 != pthread_join(threads[i], NULL)) { - perror("pthread_join"); - return 1; - } - } - - return 0; -} diff --git a/src/benchmarks/mysql.py b/src/benchmarks/mysql.py deleted file mode 100644 index 0df85d2..0000000 --- a/src/benchmarks/mysql.py +++ /dev/null @@ -1,325 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""sysbench SQL read-only benchmark - -This benchmark is heavily inspired by a blog post from Alexey Stroganov from Percona: -https://web.archive.org/web/20190706104404/https://www.percona.com/blog/2012/07/05/impact-of-memory-allocators-on-mysql-performance/ - -It uses the read-only database benchmark from sysbench, a commonly used system -benchmarking tool to measure the performance of mysqld per allocator. -The read-only benchmark on a relatively small database (~1GB) is used to omit -I/O latency and be cpu-bound, maximizing the allocators influence on performance. - -Behavior per allocator: -* Start mysqld using the allocator -* Run sysbench oltp_read_only once per thread count -* Shutdown mysqld - -40 Thread workload: - -* allocator calls: 1519226 - * malloc: 722421 (47.55%) - * free: 795231 (52.34%) - * calloc: 1501 (0.10%) - * realloc: 73 (0.004%) -* Approximate allocator ratios: - * malloc: 0.69% - * free: 0.36% - * calloc: 0.04% - -* Top 10 allocation sizes 71.36% of all allocations - 1. 288 B occurred 112556 times - 2. 4064 B occurred 112552 times - 3. 9 B occurred 61978 times - 4. 328 B occurred 56275 times - 5. 64 B occurred 48498 times - 6. 1040 B occurred 28174 times - 7. 360 B occurred 28140 times - 8. 65544 B occurred 28136 times - 9. 104 B occurred 25794 times - 10. 992 B occurred 14521 times - - allocations <= 64: 131723 18.19% - allocations <= 1024: 423315 58.47% - allocations <= 4096: 622732 86.01% - -mysqld starts one thread per connection, which produce roughly the same -allocator workload (checked with a malt trace). - -Interpretation: - -The mysql benchmark tries to be as near as possible to a real world workload. -So all non-functional characteristics of an allocator are measured. -This means the results can give hints on how each allocator performs -for a similar workload. -But the results don't directly explain why an allocator performs -this way. To obtain a more complete understanding deeper analysis of the -allocators algorithm, host system and workload is needed. -""" - -import multiprocessing -import os -import re -import shutil -from subprocess import CalledProcessError -import sys - -import numpy as np - -from src.benchmark import Benchmark -import src.facter -import src.plots as plt -from src.util import print_status, print_debug, print_info2, print_warn, run_cmd - -MYSQL_USER = "root" -RUN_TIME = 300 -TABLES = 5 - -PREPARE_CMD = ( - f"sysbench oltp_read_only --db-driver=mysql --mysql-user={MYSQL_USER} " - f"--threads={multiprocessing.cpu_count()} " - f"--mysql-socket={{build_dir}}/socket --tables={TABLES} --table-size=1000000 prepare" -) - -CMD = ( - f"sysbench oltp_read_only --threads={{nthreads}} --time={RUN_TIME} --tables={TABLES} " - f"--db-driver=mysql --mysql-user={MYSQL_USER} --mysql-socket={{build_dir}}/socket run" -) - -SERVER_CMD = ( - "mysqld --no-defaults -h {build_dir} --socket={build_dir}/socket --port=123456 " - f"--max-connections={multiprocessing.cpu_count()} --secure-file-priv=") - - -class BenchmarkMYSQL(Benchmark): - """Mysql bechmark definition""" - def __init__(self): - name = "mysql" - - self.args = {"nthreads": Benchmark.scale_threads_for_cpus(1)} - self.cmd = CMD - self.servers = [{"name": "mysqld", "cmd": SERVER_CMD}] - self.measure_cmd = "" - - self.requirements = ["mysqld", "sysbench"] - - super().__init__(name) - - self.results["facts"]["runtime [s]"] = RUN_TIME - - def reset_preparations(self): - """Reset self.build_dir if preparing fails""" - if os.path.exists(self.build_dir): - print_warn("Reset mysql test directory") - shutil.rmtree(self.build_dir, ignore_errors=True) - - def prepare(self): - super().prepare() - - # save mysqld and sysbench versions - for exe in self.requirements: - self.results["facts"]["versions"][exe] = src.facter.exe_version( - exe, "--version") - - # Setup Test Environment - if not os.path.exists(self.build_dir): - print_status("Prepare mysqld directory and database") - os.makedirs(self.build_dir) - - # Init database - if "MariaDB" in self.results["facts"]["versions"]["mysqld"]: - init_db_cmd = [ - "mysql_install_db", "--basedir=/usr", - f"--datadir={self.build_dir}" - ] - print_info2("MariaDB detected") - else: - init_db_cmd = [ - "mysqld", "-h", self.build_dir, "--initialize-insecure" - ] - print_info2("Oracle MySQL detected") - - try: - run_cmd(init_db_cmd, capture=True) - except CalledProcessError as e: - print_debug("Stdout:", e.stdout, file=sys.stderr) - print_debug("Stderr:", e.stderr, file=sys.stderr) - self.reset_preparations() - raise e - - self.start_servers() - - # Create sbtest TABLE - try: - run_cmd(f"mysql -u {MYSQL_USER} -S {self.build_dir}/socket". - split(), - input="CREATE DATABASE sbtest;\n", - capture=True, - cwd=self.build_dir) - except CalledProcessError as e: - print_debug("Stderr:", e.stderr, file=sys.stderr) - self.reset_preparations() - raise e - - print_status("Prepare test tables ...") - prepare_cmd = PREPARE_CMD.format(build_dir=self.build_dir).split() - try: - run_cmd(prepare_cmd, capture=True) - except CalledProcessError as e: - print_debug("Stdout:", e.stdout, file=sys.stderr) - print_debug("Stderr:", e.stderr, file=sys.stderr) - self.reset_preparations() - raise e - - self.shutdown_servers() - - def process_output(self, result, stdout, stderr, allocator, perm): - result["transactions"] = re.search("transactions:\\s*(\\d*)", - stdout).group(1) - result["queries"] = re.search("queries:\\s*(\\d*)", stdout).group(1) - # Latency - result["min"] = re.search("min:\\s*(\\d*.\\d*)", stdout).group(1) - result["avg"] = re.search("avg:\\s*(\\d*.\\d*)", stdout).group(1) - result["max"] = re.search("max:\\s*(\\d*.\\d*)", stdout).group(1) - - def summary(self): - allocators = self.results["allocators"] - args = self.results["args"] - - # linear plot - plt.plot(self, - "{transactions}", - fig_options={ - 'xlabel': 'threads', - 'ylabel': 'transactions', - 'title': 'sysbench oltp read only', - }, - file_postfix="l") - - # normalized linear plot - ref_alloc = list(allocators)[0] - plt.plot(self, - "{transactions}", - fig_options={ - 'xlabel': 'threads', - 'ylabel': 'transactions scaled at {scale}', - 'title': 'sysbench oltp read only', - }, - file_postfix="norm.l", - scale=ref_alloc) - - # bar plot - plt.plot(self, - "{transactions}", - plot_type='bar', - fig_options={ - 'xlabel': 'threads', - 'ylabel': 'transactions', - 'title': 'sysbench oltp read only', - }, - file_postfix="b") - - # normalized bar plot - plt.plot(self, - "{transactions}", - plot_type='bar', - fig_options={ - 'xlabel': 'threads', - 'ylabel': 'transactions scaled at {scale}', - 'title': 'sysbench oltp read only', - }, - file_postfix="norm.b", - scale=ref_alloc) - - # Memusage - plt.plot(self, - "{mysqld_vmhwm}", - plot_type='bar', - fig_options={ - 'xlabel': 'threads', - 'ylabel': 'VmHWM in kB', - 'title': 'Memusage sysbench oltp read only', - }, - file_postfix="mem") - - plt.write_tex_table(self, [{ - "label": "Transactions", - "expression": "{transactions}", - "sort": ">" - }, { - "label": "Memusage [KB]", - "expression": "{mysqld_vmhwm}", - "sort": "<" - }], - file_postfix="table") - - # Colored latex table showing transactions count - d = {allocator: {} for allocator in allocators} - for perm in self.iterate_args(args=args): - for allocator in allocators: - transactions = [ - float(measure["transactions"]) - for measure in self.results[allocator][perm] - ] - mean = np.mean(transactions) - std = np.std(transactions) / mean - d[allocator][perm] = {"mean": mean, "std": std} - - mins = {} - maxs = {} - for perm in self.iterate_args(args=args): - cmax = None - cmin = None - for i, allocator in enumerate(allocators): - m = d[allocator][perm]["mean"] - if not cmax or m > cmax: - cmax = m - if not cmin or m < cmin: - cmin = m - maxs[perm] = cmax - mins[perm] = cmin - - fname = ".".join([self.name, "transactions.tex"]) - headers = [perm.nthreads for perm in self.iterate_args(args=args)] - with open(fname, "w") as f: - print("\\begin{tabular}{| l" + " l" * len(headers) + " |}", file=f) - print("Fäden / Allokator ", end=" ", file=f) - for head in headers: - print("& {}".format(head), end=" ", file=f) - print("\\\\\n\\hline", file=f) - - for allocator in allocators: - print(allocator, end=" ", file=f) - for perm in self.iterate_args(args=args): - m = d[allocator][perm]["mean"] - s = "& \\textcolor{{{}}}{{{:.3f}}}" - if m == maxs[perm]: - color = "green" - elif m == mins[perm]: - color = "red" - else: - color = "black" - print(s.format(color, m), end=" ", file=f) - print("\\\\", file=f) - - print("\\end{tabular}", file=f) - - plt.export_stats_to_csv(self, "transactions") - plt.export_stats_to_dataref(self, "transactions") - - -mysql = BenchmarkMYSQL() diff --git a/src/benchmarks/raxmlng.py b/src/benchmarks/raxmlng.py deleted file mode 100644 index ef77d2d..0000000 --- a/src/benchmarks/raxmlng.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the RAxML-ng benchmark""" - -import os -import re - -from src.artifact import GitArtifact -from src.benchmark import Benchmark -import src.plots as plt -from src.util import print_info, run_cmd - -RUNTIME_RE = re.compile("Elapsed time: (?P<runtime>(\\d*.\\d*)) seconds") - - -class BenchmarkRaxmlng(Benchmark): - """RAxML-ng benchmark - """ - def __init__(self): - name = "raxmlng" - - super().__init__(name) - - self.cmd = ( - f"raxml-ng --msa {self.build_dir}/data/prim.phy --model GTR+G" - " --redo --threads 2 --seed 2") - - def prepare(self): - super().prepare() - - if os.path.exists(self.build_dir): - return - - raxmlng_sources = GitArtifact("raxml-ng", - "https://github.com/amkozlov/raxml-ng") - raxmlng_version = "0.9.0" - raxmlng_dir = os.path.join(self.build_dir, "raxml-ng-git") - raxmlng_builddir = os.path.join(raxmlng_dir, "build") - self.results["facts"]["versions"]["raxml-ng"] = raxmlng_version - raxmlng_sources.provide(raxmlng_version, raxmlng_dir) - - # Create builddir - os.makedirs(raxmlng_builddir, exist_ok=True) - - # building raxml-ng - run_cmd(["cmake", ".."], cwd=raxmlng_builddir) - run_cmd(["make"], cwd=raxmlng_builddir) - - # create symlinks - for exe in ["raxml-ng"]: - src = os.path.join(raxmlng_dir, "bin", exe) - dest = os.path.join(self.build_dir, exe) - os.link(src, dest) - - raxmlng_data = GitArtifact("raxml-ng-data", - "https://github.com/amkozlov/ng-tutorial") - raxmlng_data_dir = os.path.join(self.build_dir, "data") - raxmlng_data.provide("f8f0b6a057a11397b4dad308440746e3436db8b4", - raxmlng_data_dir) - - def cleanup(self): - for direntry in os.listdir(): - if direntry.startswith("prim.raxml"): - os.remove(direntry) - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - result["runtime"] = RUNTIME_RE.search(stdout).group("runtime") - - def summary(self): - plt.plot(self, - "{runtime}", - plot_type='bar', - fig_options={ - 'ylabel': 'runtime in s', - 'title': 'raxml-ng tree inference benchmark', - }, - file_postfix="runtime") - - plt.export_stats_to_dataref(self, "runtime") - - plt.plot(self, - "{VmHWM}", - plot_type='bar', - fig_options={ - 'ylabel': 'VmHWM in KB', - 'title': 'raxml-ng memusage', - }, - file_postfix="memusage") - - plt.export_stats_to_dataref(self, "VmHWM") - - -raxmlng = BenchmarkRaxmlng() diff --git a/src/benchmarks/rdtsc.py b/src/benchmarks/rdtsc.py deleted file mode 100644 index 03f8ff3..0000000 --- a/src/benchmarks/rdtsc.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the rdtsc micro benchmark - -This benchmark measures the clock cycles used by malloc. -It tries to spread the spawned thread on all cores exept the first one. -See: https://developers.redhat.com/blog/2016/03/11/practical-micro-benchmarking-with-ltrace-and-sched/ -""" - -import numpy as np -import matplotlib -import matplotlib.pyplot as plt - -from src.benchmark import Benchmark -import src.globalvars -import src.plots - - -class BenchmarkRdtsc(Benchmark): - """rdtsc micro benchmark - - This benchmark allocates and frees n blocks in t concurrent threads measuring the used cycles. - """ - def __init__(self): - name = "rdtsc" - - self.cmd = "rdtsc {mode} 100000 64 {threads}" - self.measure_cmd = "" - - self.args = {"threads": [1], - "mode": ['fresh', 'cached']} - - self.requirements = ["rdtsc"] - super().__init__(name) - - def process_output(self, result, stdout, stderr, alloc, perm): - all_cycles = [] - for line in stdout.splitlines(): - all_cycles.append(int(line.split()[1])) - result["all_cycles"] = all_cycles - result["cycles"] = np.mean(all_cycles) - - def summary(self): - for perm in self.iterate_args(args=self.results['args']): - label = f'rdtsc_{perm}_cycles' - fig = plt.figure(label) - src.plots.FIGURES[label] = fig - - axes = plt.axes() - axes.set_ylim([50, 800]) - - for i, alloc in enumerate(self.results['allocators']): - d = np.sort(self.results[alloc][perm][0]['all_cycles']) - color = src.plots._get_alloc_color(self, alloc) - color = f"C{i}" - plt.plot(d, label=alloc, color=color) - - plt.legend() - plt.title(str(perm)) - fig.savefig(f'{label}.{src.globalvars.summary_file_ext}') - plt.show() - - - src.plots.export_stats_to_csv(self, "cycles") - - -rdtsc = BenchmarkRdtsc() diff --git a/src/benchmarks/rdtsc/Makefile b/src/benchmarks/rdtsc/Makefile deleted file mode 100644 index f81a84b..0000000 --- a/src/benchmarks/rdtsc/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -pthread -OPTFLAGS ?= -O0 -g - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -.PHONY = all clean - -all: $(OBJDIR)/rdtsc - -$(OBJDIR)/rdtsc: rdtsc.c Makefile | $(OBJDIR) - @echo compiling $@... - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/rdtsc/rdtsc.c b/src/benchmarks/rdtsc/rdtsc.c deleted file mode 100644 index fec84d6..0000000 --- a/src/benchmarks/rdtsc/rdtsc.c +++ /dev/null @@ -1,105 +0,0 @@ -#define _GNU_SOURCE /* See feature_test_macros(7) */ -#include <pthread.h> -#include <sched.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/sysinfo.h> - -int mode = 0; -int size = 64; -int iterations = 100000; -int num_cpus; - -static __inline__ int64_t rdtsc_s(void) -{ - unsigned a, d; - asm volatile("cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx"); - asm volatile("rdtsc" : "=a" (a), "=d" (d)); - return ((unsigned long)a) | (((unsigned long)d) << 32); -} - -static __inline__ int64_t rdtsc_e(void) -{ - unsigned a, d; - asm volatile("rdtscp" : "=a" (a), "=d" (d)); - asm volatile("cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx"); - return ((unsigned long)a) | (((unsigned long)d) << 32); -} - -static void* test_thread_func(void* arg) { - int64_t clock_before, clock_after; - void* p; - - int64_t* clocks = malloc(iterations * sizeof(int64_t)); - if (!clocks) - abort(); - - // set cpu affinity to prevent cpu switching - int64_t tid = (int64_t) arg; - cpu_set_t my_cpu; - /* Skip CPU0 - let the OS run on that one */ - int my_cpu_num = (tid % (num_cpus-1))+1; - - CPU_ZERO (&my_cpu); - CPU_SET (my_cpu_num, &my_cpu); - if (sched_setaffinity (0, sizeof(my_cpu), &my_cpu) == -1) - perror ("setaffinity failed"); - - for(int i = 0; i < iterations; i++) { - clock_before = rdtsc_s(); - p = malloc(size); - clock_after = rdtsc_e(); - - // measure potentially cached allocations - if (mode) - free(p); - - clocks[i] = clock_after - clock_before; - } - - for(int i = 0; i < iterations; i++) { - printf("malloc(%d): %d cycles\n", size, clocks[i]); - } - - return NULL; -} - -int main(int argc, char* argv[]) { - pthread_t* threads; - int num_threads = 1; - - num_cpus = get_nprocs(); - - if (argc > 5) { - fprintf(stderr, "Usage: %s <iterations> <size> <num threads>\n", argv[0]); - return 1; - } - - if (argc > 1) { - if (strncmp(argv[1], "cached", strlen("cached")) == 0) mode = 1; - } - if (argc > 2) iterations = atoi(argv[2]); - if (argc > 3) size = atoi(argv[3]); - if (argc > 4) num_threads = atoi(argv[4]); - - fprintf(stderr, "iterations = %d; size = %d; threads = %d\n", iterations, size, num_threads); - - threads = (pthread_t*) malloc(num_threads * sizeof(pthread_t)); - - for (int i = 0; i < num_threads; i++) { - if (0 != pthread_create(&threads[i], NULL, test_thread_func, NULL)) { - perror("pthread_create"); - return 1; - } - } - - for(int i = 0; i < num_threads; i++) { - if (0 != pthread_join(threads[i], NULL)) { - perror("pthread_join"); - return 1; - } - } - - return 0; -} diff --git a/src/benchmarks/realloc.py b/src/benchmarks/realloc.py deleted file mode 100644 index d3375ff..0000000 --- a/src/benchmarks/realloc.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the realloc micro benchmark""" - -import src.plots as plt -from src.benchmark import Benchmark - - -class BenchmarkRealloc(Benchmark): - """Realloc micro benchmark - - realloc a pointer 100 times - """ - def __init__(self): - name = "realloc" - - self.cmd = "realloc" - - self.requirements = ["realloc"] - super().__init__(name) - - def summary(self): - plt.plot(self, - "{task-clock}", - plot_type='bar', - fig_options={ - 'ylabel': 'task-clock in ms', - 'title': 'realloc micro benchmark', - }, - file_postfix="time") - - plt.export_stats_to_csv(self, "task-clock") - plt.export_stats_to_dataref(self, "task-clock") - - -realloc = BenchmarkRealloc() diff --git a/src/benchmarks/realloc/Makefile b/src/benchmarks/realloc/Makefile deleted file mode 100644 index 66b38ca..0000000 --- a/src/benchmarks/realloc/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -OBJDIR ?= obj - -CC ?= gcc - -WARNFLAGS ?= -Wall -Wextra -COMMONFLAGS ?= -fno-builtin -fPIC -DPIC -pthread -OPTFLAGS ?= -O3 -DNDEBUG - -CFLAGS ?= $(OPTFLAGS) $(WARNFLAGS) $(COMMONFLAGS) - -LDFLAGS ?= -pthread -static-libgcc - -.PHONY = all clean - -all: $(OBJDIR)/realloc - -$(OBJDIR)/realloc: realloc.c | $(OBJDIR) - @echo compiling $@... - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $< - -$(OBJDIR): - mkdir -p $@ - -clean: - rm -rf $(OBJDIR) diff --git a/src/benchmarks/realloc/realloc.c b/src/benchmarks/realloc/realloc.c deleted file mode 100644 index b6e6034..0000000 --- a/src/benchmarks/realloc/realloc.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -size_t* array; -size_t steps = 1; -int main() { - for (int i = 1; i < 100; i++) { - if ((array = realloc(array, sizeof(size_t) * steps * i)) == NULL) { - perror("realloc"); - return 1; - } - } - return 0; -} diff --git a/src/benchmarks/redis.py b/src/benchmarks/redis.py deleted file mode 100644 index 265d825..0000000 --- a/src/benchmarks/redis.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the redis benchmark - - -This benchmark uses the redis benchmark tool included in the redis release -archive. The used parameters are inspired by the ones used in mimalloc-bench." -""" - -import os -import re -import sys - -from src.artifact import ArchiveArtifact -from src.benchmark import Benchmark -import src.plots as plt -from src.util import print_info, run_cmd - -REQUESTS_RE = re.compile("(?P<requests>(\\d*.\\d*)) requests per second") - - -class BenchmarkRedis(Benchmark): - """Definition of the redis benchmark""" - def __init__(self): - name = "redis" - - self.cmd = "redis-benchmark 1000000 -n 1000000 -P 8 -q lpush a 1 2 3 4 5 6 7 8 9 10 lrange a 1 10" - self.servers = [{ - "name": "redis", - "cmd": "redis-server", - "shutdown_cmds": ["{build_dir}/redis-cli shutdown"] - }] - - super().__init__(name) - - def prepare(self): - super().prepare() - - redis_version = "5.0.5" - self.results["facts"]["versions"]["redis"] = redis_version - redis = ArchiveArtifact( - "redis", - f"http://download.redis.io/releases/redis-{redis_version}.tar.gz", - "tar", "71e38ae09ac70012b5bc326522b976bcb8e269d6") - - redis_dir = os.path.join(self.build_dir, f"redis-{redis_version}") - - redis.provide(self.build_dir) - - # building redis - run_cmd(["make", "-C", redis_dir, "MALLOC=libc", "USE_JEMALLOC=no"]) - - # create symlinks - for exe in ["redis-cli", "redis-server", "redis-benchmark"]: - src = os.path.join(redis_dir, "src", exe) - dest = os.path.join(self.build_dir, exe) - if not os.path.exists(dest): - os.link(src, dest) - - @staticmethod - def process_output(result, stdout, stderr, allocator, perm): - result["requests"] = REQUESTS_RE.search(stdout).group("requests") - - @staticmethod - def cleanup(): - if os.path.exists("dump.rdb"): - os.remove("dump.rdb") - - def summary(self): - plt.plot(self, - "{requests}", - plot_type='bar', - fig_options={ - 'ylabel': 'requests per s', - 'title': 'redis throughput', - }, - file_postfix="requests") - - plt.plot(self, - "{redis_vmhwm}", - plot_type='bar', - fig_options={ - 'ylabel': '"VmHWM in KB"', - 'title': '"redis memusage"', - }, - file_postfix="vmhwm") - - plt.export_stats_to_dataref(self, "requests") - - -redis = BenchmarkRedis() diff --git a/src/benchmarks/redis/build.sh b/src/benchmarks/redis/build.sh deleted file mode 100755 index e58cb43..0000000 --- a/src/benchmarks/redis/build.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -REDIS_VERSION=5.0.5 -REDIS_DIR=redis-${REDIS_VERSION} -REDIS_ARCHIVE=${REDIS_DIR}.tar.gz -REDIS_URL=http://download.redis.io/releases/${REDIS_ARCHIVE} - -if [[ $# -gt 0 ]] -then - OBJDIR=$1 -else - OBJDIR=obj -fi - -mkdir -p $OBJDIR -cd $OBJDIR - -if [[ ! -d "${OBJDIR}/redis-${REDIS_VERSION}" ]] -then - echo retrievinug ${REDIS_DIR}... - wget ${REDIS_URL} - - echo extracting ${REDIS_ARCHIVE}... - tar xf ${REDIS_ARCHIVE} -fi - -echo building ${REDIS_DIR}... -make -C ${REDIS_DIR} - -echo linking redis-cli... -ln -s -f ${REDIS_DIR}/src/redis-cli - -echo linking redis-server... -ln -s -f ${REDIS_DIR}/src/redis-server - -echo linking redis-benchmark... -ln -s -f ${REDIS_DIR}/src/redis-benchmark diff --git a/src/benchmarks/t_test1.py b/src/benchmarks/t_test1.py deleted file mode 100644 index 2d86bdc..0000000 --- a/src/benchmarks/t_test1.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Definition of the commonly used t-test1 allocator test""" - -from src.benchmark import Benchmark -import src.plots as plt - - -class BenchmarkTTest1(Benchmark): - """t-test1 unit test - - This benchmark from ptmalloc2 allocates and frees n bins in t concurrent threads. - """ - def __init__(self): - name = "t_test1" - - self.cmd = "t-test1 {nthreads} {nthreads} 1000000 {maxsize}" - - self.args = { - "maxsize": [2**x for x in range(6, 18)], - "nthreads": Benchmark.scale_threads_for_cpus(2) - } - - self.requirements = ["t-test1"] - super().__init__(name) - - def summary(self): - # mops / per second - yval = "perm.nthreads / ({task-clock}/1000)" - # Speed - plt.plot(self, - yval, - fig_options={ - 'ylabel': 'Mops / CPU second', - 'title': 't-test1: {fixed_part_str}', - 'autoticks': False, - }, - file_postfix="time") - - # L1 cache misses - plt.plot(self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - fig_options={ - 'ylabel': 'L1 misses in %', - 'title': 't-test1 l1 cache misses: {fixed_part_str}', - 'autoticks': False, - }, - file_postfix="l1misses") - - # Speed Matrix - plt.write_best_doublearg_tex_table(self, yval, file_postfix="mops.matrix") - - plt.write_tex_table(self, [{ - "label": "MOPS/s", - "expression": yval, - "sort": ">" - }], - file_postfix="mops.table") - - plt.export_stats_to_csv(self, "task-clock") - - -t_test1 = BenchmarkTTest1() diff --git a/src/benchmarks/t_test1/Makefile b/src/benchmarks/t_test1/Makefile deleted file mode 100644 index 62a62ee..0000000 --- a/src/benchmarks/t_test1/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# Makefile for t-test1 from ptmalloc, version 2 -# by Florian Fischer 2019, 2020 -# derived from -# Makefile for ptmalloc, version 2 -# by Wolfram Gloger 1996-1999, 2001, 2002, 2003, 2004, 2006 - -OBJDIR ?= obj - -CC ?= cc - -SYS_FLAGS = -D_GNU_SOURCE=1 -OPT_FLAGS ?= -g -O # -O2 -WARN_FLAGS ?= -Wall -Wstrict-prototypes - -# Flags for the test programs -T_FLAGS = -DTEST=1 - -# Thread flags. -THR_LIBS = -lpthread - -RM = rm -f - -CFLAGS ?= $(SYS_FLAGS) $(OPT_FLAGS) $(WARN_FLAGS) - -all: $(OBJDIR)/t-test1 - -$(OBJDIR)/t-test1: t-test1.c | $(OBJDIR) - @echo compiling $@ - $(CC) $(CFLAGS) $(T_FLAGS) t-test1.c $(THR_LIBS) -o $@ - -$(OBJDIR): - mkdir -p $@ - -clean: - $(RM) -rf $(OBJDIR) diff --git a/src/benchmarks/t_test1/t-test1.c b/src/benchmarks/t_test1/t-test1.c deleted file mode 100644 index 7418693..0000000 --- a/src/benchmarks/t_test1/t-test1.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * $Id: t-test1.c,v 1.1.1.1 2003/07/02 16:32:09 matthias.urban Exp $ - * by Wolfram Gloger 1996-1999 - * A multi-thread test for malloc performance, maintaining one pool of - * allocated bins per thread. - * - * Fixed condition variable usage, and ported to windows - * Steven Fuerst 2009 - */ - -/* Testing level */ -#ifndef TEST -#define TEST 0 -#endif - -#define N_TOTAL 500 -#ifndef N_THREADS -#define N_THREADS 2 -#endif -#ifndef N_TOTAL_PRINT -#define N_TOTAL_PRINT 50 -#endif -#define STACKSIZE 32768 -#ifndef MEMORY -#define MEMORY (1ULL << 26) -#endif - -#define RANDOM(s) (rng() % (s)) - -#define MSIZE 10000 -#define I_MAX 10000 -#define ACTIONS_MAX 30 - -#include <pthread.h> - -#if (defined __STDC__ && __STDC__) || defined __cplusplus -# include <stdlib.h> -#endif - -#include <stdio.h> -#include <unistd.h> - -#ifdef __GCC__ -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/wait.h> -#endif - -#include <sys/types.h> -#include <malloc.h> - - -/* - * Ultra-fast RNG: Use a fast hash of integers. - * 2**64 Period. - * Passes Diehard and TestU01 at maximum settings - */ -static __thread unsigned long long rnd_seed; - -static inline unsigned rng(void) -{ - unsigned long long c = 7319936632422683443ULL; - unsigned long long x = (rnd_seed += c); - - x ^= x >> 32; - x *= c; - x ^= x >> 32; - x *= c; - x ^= x >> 32; - - /* Return lower 32bits */ - return x; -} - -/* For large allocation sizes, the time required by copying in - realloc() can dwarf all other execution times. Avoid this with a - size threshold. */ -#ifndef REALLOC_MAX -#define REALLOC_MAX 2000 -#endif - -struct bin -{ - unsigned char *ptr; - size_t size; -}; - -static pthread_cond_t finish_cond; -static pthread_mutex_t finish_mutex; - -#if TEST > 0 - -static void mem_init(unsigned char *ptr, size_t size) -{ - size_t i, j; - - if (!size) return; - for (i = 0; i < size; i += 2047) - { - j = (size_t)ptr ^ i; - ptr[i] = j ^ (j>>8); - } - j = (size_t)ptr ^ (size - 1); - ptr[size-1] = j ^ (j>>8); -} - -static int mem_check(unsigned char *ptr, size_t size) -{ - size_t i, j; - - if (!size) return 0; - for (i = 0; i < size; i += 2047) - { - j = (size_t)ptr ^ i; - if (ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 1; - } - j = (size_t)ptr ^ (size - 1); - if (ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2; - return 0; -} - -static int zero_check(void *p, size_t size) -{ - unsigned *ptr = p; - unsigned char *ptr2; - - while (size >= sizeof(*ptr)) - { - if (*ptr++) return -1; - size -= sizeof(*ptr); - } - ptr2 = (unsigned char*)ptr; - - while (size > 0) - { - if (*ptr2++) return -1; - --size; - } - return 0; -} - -#endif /* TEST > 0 */ - -/* - * Allocate a bin with malloc(), realloc() or memalign(). - * r must be a random number >= 1024. - */ -static void bin_alloc(struct bin *m, size_t size, unsigned r) -{ -#if TEST > 0 - if (mem_check(m->ptr, m->size)) - { - printf("memory corrupt!\n"); - exit(1); - } -#endif - r %= 1024; - - if (r < 4) - { - /* memalign */ - if (m->size > 0) free(m->ptr); - m->ptr = memalign(sizeof(int) << r, size); - } - else if (r < 20) - { - /* calloc */ - if (m->size > 0) free(m->ptr); - m->ptr = calloc(size, 1); -#if TEST > 0 - if (zero_check(m->ptr, size)) - { - size_t i; - for (i = 0; i < size; i++) - { - if (m->ptr[i]) break; - } - printf("calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i); - exit(1); - } -#endif - } - else if ((r < 100) && (m->size < REALLOC_MAX)) - { - /* realloc */ - if (!m->size) m->ptr = NULL; - m->ptr = realloc(m->ptr, size); - } - else - { - /* malloc */ - if (m->size > 0) free(m->ptr); - m->ptr = malloc(size); - } - if (!m->ptr) - { - printf("out of memory (r=%d, size=%ld)!\n", r, (unsigned long)size); - exit(1); - } - - m->size = size; -#if TEST > 0 - mem_init(m->ptr, m->size); -#endif -} - -/* Free a bin. */ - -static void bin_free(struct bin *m) -{ - if (!m->size) return; - -#if TEST > 0 - if (mem_check(m->ptr, m->size)) - { - printf("memory corrupt!\n"); - exit(1); - } -#endif - - free(m->ptr); - m->size = 0; -} - -struct bin_info -{ - struct bin *m; - size_t size, bins; -}; - -struct thread_st -{ - int bins, max, flags; - size_t size; - pthread_t id; - char *sp; - size_t seed; -}; - -static void *malloc_test(void *ptr) -{ - struct thread_st *st = ptr; - int i, pid = 1; - unsigned b, j, actions; - struct bin_info p; - - rnd_seed = st->seed; - - p.m = malloc(st->bins * sizeof(*p.m)); - p.bins = st->bins; - p.size = st->size; - for (b = 0; b < p.bins; b++) - { - p.m[b].size = 0; - p.m[b].ptr = NULL; - if (!RANDOM(2)) bin_alloc(&p.m[b], RANDOM(p.size) + 1, rng()); - } - - for (i = 0; i <= st->max;) - { - actions = RANDOM(ACTIONS_MAX); - - for (j = 0; j < actions; j++) - { - b = RANDOM(p.bins); - bin_free(&p.m[b]); - } - i += actions; - actions = RANDOM(ACTIONS_MAX); - - for (j = 0; j < actions; j++) - { - b = RANDOM(p.bins); - bin_alloc(&p.m[b], RANDOM(p.size) + 1, rng()); - } - - i += actions; - } - - for (b = 0; b < p.bins; b++) bin_free(&p.m[b]); - - free(p.m); - - if (pid > 0) - { - pthread_mutex_lock(&finish_mutex); - st->flags = 1; - pthread_cond_signal(&finish_cond); - pthread_mutex_unlock(&finish_mutex); - } - return NULL; -} - -static int my_start_thread(struct thread_st *st) -{ - pthread_create(&st->id, NULL, malloc_test, st); - return 0; -} - -static int n_total = 0; -static int n_total_max = N_TOTAL; -static int n_running; - -static int my_end_thread(struct thread_st *st) -{ - /* Thread st has finished. Start a new one. */ - if (n_total >= n_total_max) - { - n_running--; - } - else if (st->seed++, my_start_thread(st)) - { - printf("Creating thread #%d failed.\n", n_total); - } - else - { - n_total++; - if (!(n_total%N_TOTAL_PRINT)) printf("n_total = %d\n", n_total); - } - return 0; -} - -int main(int argc, char *argv[]) -{ - int i, bins; - int n_thr = N_THREADS; - int i_max = I_MAX; - size_t size = MSIZE; - struct thread_st *st; - - if (argc > 1) n_total_max = atoi(argv[1]); - if (n_total_max < 1) n_thr = 1; - if (argc > 2) n_thr = atoi(argv[2]); - if (n_thr < 1) n_thr = 1; - if (n_thr > 100) n_thr = 100; - if (argc > 3) i_max = atoi(argv[3]); - - if (argc > 4) size = atol(argv[4]); - if (size < 2) size = 2; - - bins = MEMORY /(size * n_thr); - if (argc > 5) bins = atoi(argv[5]); - if (bins < 4) bins = 4; - - printf("Using posix threads.\n"); - pthread_cond_init(&finish_cond, NULL); - pthread_mutex_init(&finish_mutex, NULL); - - printf("total=%d threads=%d i_max=%d size=%ld bins=%d\n", - n_total_max, n_thr, i_max, size, bins); - - st = malloc(n_thr * sizeof(*st)); - if (!st) exit(-1); - - pthread_mutex_lock(&finish_mutex); - - /* Start all n_thr threads. */ - for (i = 0; i < n_thr; i++) - { - st[i].bins = bins; - st[i].max = i_max; - st[i].size = size; - st[i].flags = 0; - st[i].sp = 0; - st[i].seed = (i_max * size + i) ^ bins; - if (my_start_thread(&st[i])) - { - printf("Creating thread #%d failed.\n", i); - n_thr = i; - break; - } - printf("Created thread %lx.\n", (long)st[i].id); - } - - for (n_running = n_total = n_thr; n_running > 0;) - { - - /* Wait for subthreads to finish. */ - pthread_cond_wait(&finish_cond, &finish_mutex); - for (i = 0; i < n_thr; i++) - { - if (st[i].flags) - { - pthread_join(st[i].id, NULL); - st[i].flags = 0; - my_end_thread(&st[i]); - } - } - } - pthread_mutex_unlock(&finish_mutex); - - for (i = 0; i < n_thr; i++) - { - if (st[i].sp) free(st[i].sp); - } - free(st); - // Print malloc_stats to stdout - close(STDERR_FILENO); - dup2(STDOUT_FILENO, STDERR_FILENO); - malloc_stats(); - printf("Done.\n"); - return 0; -} - diff --git a/src/bumpptr_alloc.c b/src/bumpptr_alloc.c deleted file mode 100644 index ee2928a..0000000 --- a/src/bumpptr_alloc.c +++ /dev/null @@ -1,64 +0,0 @@ -#include <assert.h> -#include <errno.h> -#include <stddef.h> /* NULL, size_t */ -#include <stdint.h> /* uintptr_t */ -#include <stdio.h> /* fprintf */ -#include <sys/mman.h> /* mmap */ - -#define MIN_ALIGNMENT 16 - -#ifndef MEMSIZE -#define MEMSIZE 1024*4*1024*1024l -#endif - -#define unlikely(x) __builtin_expect((x),0) - -typedef struct bumpptr { - uintptr_t end; - uintptr_t ptr; -} bumpptr_t; - -__thread bumpptr_t* tsd = NULL; - -static inline void* bump_up(size_t size, size_t align) { - assert(align % 2 == 0); - - if (unlikely(tsd == NULL)) { - void* mem_start = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); - if(mem_start == MAP_FAILED) { - perror("mmap"); - return NULL; - } - tsd = (bumpptr_t*)mem_start; - tsd->ptr = (uintptr_t)mem_start + sizeof(bumpptr_t); - tsd->end = (uintptr_t)mem_start + MEMSIZE; - } - - // align ptr; - uintptr_t aligned = (tsd->ptr + align - 1) & ~(align - 1); - - uintptr_t new_ptr = aligned + size; - if (new_ptr > tsd->end) { - errno = ENOMEM; - return NULL; - } else { - tsd->ptr = new_ptr; - return (void*)aligned; - } -} - -void* malloc(size_t size) { - return bump_up(size, MIN_ALIGNMENT); -} - -void free(__attribute__ ((unused)) void* ptr) { -} - -void* memalign(size_t alignment, size_t size) { - return bump_up(size, alignment); -} - -void malloc_stats() { - fprintf(stderr, "Bump pointer allocator by muhq\n"); - fprintf(stderr, "Memsize: %zu, start address: %p, bump pointer %p\n", MEMSIZE, tsd, tsd->ptr); -} diff --git a/src/exec.c b/src/exec.c deleted file mode 100644 index 6985fb2..0000000 --- a/src/exec.c +++ /dev/null @@ -1,35 +0,0 @@ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -int main(int argc, char* argv[]) { - if (argc < 2) { - printf("Usage: %s [-p LD_PRELOAD] [-l LD_LIBRARY_PATH] <cmd> [cmd args]\n", argv[0]); - printf("\tset LD_PRELOAD to ld_preload and call execvp <cmd> [cmd args]\n"); - return 1; - } - - int i = 1; - for (; i < argc; i++) { - // Overwrite LD_PRELOAD. - if (strncmp(argv[i], "-p", 2) == 0) { - setenv("LD_PRELOAD", argv[i+1], 1); - i++; - // Overwrite LD_LIBRARY_PATH. - } else if (strncmp(argv[i], "-l", 2) == 0) { - setenv("LD_LIBRARY_PATH", argv[i+1], 1); - i++; - } else { - break; - } - } - - // Run cmd. - execvp(argv[i], &argv[i]); - - fprintf(stderr, "executing %s failed\n", argv[i]); - - return 1; -} diff --git a/src/facter.py b/src/facter.py deleted file mode 100644 index 5141b78..0000000 --- a/src/facter.py +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Collect facts about the benchmark environment""" - -import ctypes -import datetime -import errno -import json -import multiprocessing -import os -import platform -from subprocess import CalledProcessError - -import src.globalvars as gv -from src.util import print_debug, print_info, print_warn, run_cmd - -FACTS = {} - -def collect_facts(): - """Collect general facts about the benchmark environment""" - # Populate src.globalvars.facts on import - _uname = platform.uname() - FACTS["hostname"] = _uname.node - FACTS["system"] = _uname.system - FACTS["kernel"] = _uname.release - FACTS["arch"] = _uname.machine - FACTS["cpus"] = multiprocessing.cpu_count() - FACTS["LD_PRELOAD"] = os.environ.get("LD_PRELOAD", None) - - with open(os.path.join(gv.builddir, "ccinfo"), "r") as ccinfo: - FACTS["cc"] = ccinfo.readlines()[-1][:-1] - - # get commit info from git - allocbench_version() - - starttime = datetime.datetime.now().isoformat() - # strip seconds from string - starttime = starttime[:starttime.rfind(':')] - FACTS["starttime"] = starttime - - -def store_facts(path=None): - """Store facts to file""" - if not path: - filename = "facts.json" - elif os.path.isdir(path): - filename = os.path.join(path, "facts.json") - else: - filename = path - - print_info(f"Saving facts to: {filename}") - with open(filename, "w") as f: - json.dump(FACTS, f) - - -def load_facts(path=None): - """Load facts from file""" - if not path: - filename = "facts" - else: - if os.path.isdir(path): - filename = os.path.join(path, "facts") - else: - filename = os.path.splitext(path)[0] - - if os.path.exists(filename + ".json"): - filename += ".json" - global FACTS - with open(filename, "r") as f: - FACTS = json.load(f) - elif os.path.exists(filename + ".save"): - import pickle - filename += ".save" - with open(filename, "rb") as f: - FACTS = pickle.load(f) - else: - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), - filename) - - print_info(f"Loading facts from: {filename}") - -def allocbench_version(): - "Store and return allocbench version string.""" - if "allocbench" in FACTS: - return FACTS["allocbench"] - - commit = run_cmd(["git", "rev-parse", "HEAD"], capture=True).stdout[:-1] - - proc = run_cmd(["git", "status", "--porcelain"], capture=True) - dirty = "-dirty" if proc.stdout != "" else "" - - FACTS["allocbench"] = f"{commit}{dirty}" - return FACTS["allocbench"] - - -# Copied from pip. -# https://github.com/pypa/pip/blob/master/src/pip/_internal/utils/glibc.py -# Licensed under MIT. -def glibc_version_string(executable=None): - "Returns glibc version string, or None if not using glibc." - - # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen - # manpage says, "If filename is NULL, then the returned handle is for the - # main program". This way we can let the linker do the work to figure out - # which libc our process is actually using. - try: - process_namespace = ctypes.CDLL(executable) - except OSError: - return None - - try: - gnu_get_libc_version = process_namespace.gnu_get_libc_version - except AttributeError: - # Symbol doesn't exist -> therefore, we are not linked to - # glibc. - return None - - # Call gnu_get_libc_version, which returns a string like "2.5" - gnu_get_libc_version.restype = ctypes.c_char_p - version_str = gnu_get_libc_version() - # py2 / py3 compatibility: - if not isinstance(version_str, str): - version_str = version_str.decode("ascii") - - return version_str - - -# platform.libc_ver regularly returns completely nonsensical glibc -# versions. E.g. on my computer, platform says: -# -# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.7') -# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.9') -# -# But the truth is: -# -# ~$ ldd --version -# ldd (Debian GLIBC 2.22-11) 2.22 -# -# This is unfortunate, because it means that the linehaul data on libc -# versions that was generated by pip 8.1.2 and earlier is useless and -# misleading. Solution: instead of using platform, use our code that actually -# works. -def libc_ver(executable=None): - """Return glibc version or platform.libc_ver as fallback""" - glibc_version = glibc_version_string(executable) - if glibc_version is None: - # For non-glibc platforms, fall back on platform.libc_ver - return platform.libc_ver(executable) - - return ("glibc", glibc_version) - - -def exe_version(executable, version_flag="--version"): - """Return version of executable""" - try: - proc = run_cmd([executable, version_flag], capture=True) - except CalledProcessError as e: - print_warn(f"failed to get version of {executable}") - print_debug(e.stderr) - return "" - - return proc.stdout[:-1] diff --git a/src/globalvars.py b/src/globalvars.py deleted file mode 100644 index 474c124..0000000 --- a/src/globalvars.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. - -"""Global variables for allocbench - -verbosity: Verbosity level -1: quiet, 0: status, 1: info, 2: stdout of subcommands, 3: debug info -allocators: Dict holding the allocators to compare -benchmarks: List of available benchmarks - -allocbenchdir: Root directory of allocbench -srcdir: Directory of allocbench sources -benchsrcdir: Source directory for all benchmarks -allocsrcdir: Source directory for all benchmarks -builddir: Path of the build directory -allocbuilddir: Path of the allocators build directory -resdir: Directory were the benchmark results are stored -""" - -import inspect -import os - - -verbosity = 0 - -allocators = {} - -# allocbench/src/ -srcdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) - -# allocbench/src/benchmarks -benchsrcdir = os.path.join(srcdir, "benchmarks") - -# allocbench/src/allocators -allocsrcdir = os.path.join(srcdir, "allocators") - -# allocbench -allocbenchdir = os.path.dirname(srcdir) - -# allocbench/build -builddir = os.path.join(allocbenchdir, "build") - -# allocbench/build/allocators -allocbuilddir = os.path.join(builddir, "allocators") - -resdir = None - -benchmarks = [e[:-3] for e in os.listdir(os.path.join(allocbenchdir, benchsrcdir)) - if e[-3:] == ".py" and e != "__init__.py"] - -summary_file_ext = "svg" - -latex_custom_preamble = "" diff --git a/src/malloc.c b/src/malloc.c deleted file mode 100644 index 92265cb..0000000 --- a/src/malloc.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <malloc.h> /* memalign */ -#include <stdlib.h> /* malloc, free */ -#include <stddef.h> /* NULL, size_t */ -#include <stdint.h> /* uintptr_t */ -#include <string.h> /* memcpy */ -#include <unistd.h> /* sysconf */ - -#ifdef __cplusplus -extern "C" { -#endif - -void* realloc(void* ptr, size_t size) { - if(ptr == NULL) - return malloc(size); - - void* new_ptr = malloc(size); - // this may copies to much - memcpy(new_ptr, ptr, size); - return new_ptr; -} - -int posix_memalign(void **memptr, size_t alignment, size_t size) -{ - void *out; - - if((alignment % sizeof(void*)) != 0) { - return 22; - } - - /* if not power of two */ - if(!((alignment != 0) && !(alignment & (alignment - 1)))) { - return 22; - } - - if(size == 0) { - *memptr = NULL; - return 0; - } - - out = malloc(size); - if(out == NULL) { - return 12; - } - - *memptr = out; - return 0; -} - -void* calloc(size_t nmemb, size_t size) -{ - void *out; - size_t fullsize = nmemb * size; - - if((size != 0) && ((fullsize / size) != nmemb)) { - return NULL; - } - - out = malloc(fullsize); - if(out == NULL) { - return NULL; - } - - memset(out, 0, fullsize); - return out; -} - -void* valloc(size_t size) -{ - long ret = sysconf(_SC_PAGESIZE); - if(ret == -1) { - return NULL; - } - - return memalign(ret, size); -} - -void* pvalloc(size_t size) -{ - size_t ps, rem, allocsize; - - long ret = sysconf(_SC_PAGESIZE); - if(ret == -1) { - return NULL; - } - - ps = ret; - rem = size % ps; - allocsize = size; - if(rem != 0) { - allocsize = ps + (size - rem); - } - - return memalign(ps, allocsize); -} - -void* aligned_alloc(size_t alignment, size_t size) -{ - if(alignment > size) { - return NULL; - } - - if((size % alignment) != 0) { - return NULL; - } - - return memalign(alignment, size); -} - -#ifdef __cplusplus -} -#endif diff --git a/src/plots.py b/src/plots.py deleted file mode 100644 index fb39578..0000000 --- a/src/plots.py +++ /dev/null @@ -1,771 +0,0 @@ -# Copyright 2018-2020 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Plot different graphs from allocbench results""" - -import copy -import itertools -import matplotlib -import matplotlib.pyplot as plt -import numpy as np -import os -import traceback - -import src.globalvars -from src.util import print_debug, print_warn - -# This is useful when evaluating strings in the plot functions. str(np.NaN) == "nan" -nan = np.NaN - -DEFAULT_PLOT_OPTIONS = { - 'plot': { - 'marker': '.', - 'linestyle': '-', - }, - 'errorbar': { - 'marker': '.', - 'linestyle': '-', - 'yerr': True, - }, - 'bar': { - 'yerr': True, - } -} - -DEFAULT_FIG_OPTIONS = { - 'plot': { - 'legend': True, - 'legend_pos': 'best', - 'autoticks': True, - }, - 'errorbar': { - 'legend': True, - 'legend_pos': 'best', - 'autoticks': True, - }, - 'bar': { - 'legend': True, - 'legend_pos': 'lower center', - 'autoticks': False, - } -} - -FIGURES = {} - -def _get_alloc_color(bench, alloc): - """Populate all not set allocator colors with matplotlib 'C' colors""" - if isinstance(alloc, str): - alloc = bench.results["allocators"][alloc] - if alloc["color"] is None: - allocs = bench.results["allocators"] - explicit_colors = [ - v["color"] for v in allocs.values() if v["color"] is not None - ] - matplotlib_c_colors = ["C" + str(i) for i in range(0, 10)] - avail_colors = [ - c for c in matplotlib_c_colors if c not in explicit_colors - ] - - for alloc in allocs.values(): - if alloc["color"] is None: - alloc["color"] = avail_colors.pop() - - return alloc["color"] - - -def _eval_with_stat(bench, evaluation, alloc, perm, stat): - """Helper to evaluate a datapoint description string""" - try: - res = evaluation.format(**bench.results["stats"][alloc][perm][stat]) - except KeyError: - print_debug(traceback.format_exc()) - print_warn( - f"KeyError while expanding {evaluation} for {alloc} and {perm}") - return nan - return eval(res) - - -def _get_y_data(bench, expression, allocator, perms, stat="mean", scale=None): - """Helper to get the y data of an allocator for given permutations""" - y_data = [] - for perm in perms: - if scale: - if scale == allocator: - y_data.append(1) - else: - val = _eval_with_stat(bench, expression, allocator, perm, stat) - norm_val = _eval_with_stat(bench, expression, scale, perm, - stat) - y_data.append(val / norm_val) - else: - y_data.append( - _eval_with_stat(bench, expression, allocator, perm, stat)) - - return y_data - -def _create_plot_options(plot_type, **kwargs): - """ - Create a plot options dictionary. - - Parameters - ---------- - plot_type : str - The plot type for which the options should be created. - Possible values: {'bar', 'errorbar', 'plot'} - - **kwargs : plot properties, optional - *kwargs* are used to specify properties like a line label (for - auto legends), linewidth, antialiasing, marker face color. - - Returns - ------- - options : dict - Dict holding the specified options and all default values for plot type - """ - - options = copy.deepcopy(DEFAULT_PLOT_OPTIONS[plot_type]) - for key, value in kwargs.items(): - options[key] = value - - return options - -def _create_figure_options(plot_type, fig_label, **kwargs): - """ - Create a figure options dictionary - - Parameters - ---------- - plot_type : str - The plot type for which the options should be created. - Possible values: {'bar', 'errorbar', 'plot'} - - **kwargs : figure properties, optional - *kwargs* are used to specify properties like legends, legend position, - x-/ and ylabel, and title. - - Returns - ------- - options : dict - Dict holding the specified options and all default values for plot type - """ - - options = copy.deepcopy(DEFAULT_FIG_OPTIONS[plot_type]) - - options['fig_label'] = fig_label - - for key, value in kwargs.items(): - options[key] = value - - return options - -def _plot(bench, - allocators, - y_expression, - x_data, - perms, - plot_type, - plot_options, - fig_options, - scale=None, - file_postfix="", - sumdir="", - file_ext=src.globalvars.summary_file_ext): - """ - Create a plot for a given expression - - Parameters - ---------- - - Returns - ------- - figure : :rc:`~matplotlib.figure.Figure` - The new :rc:`.Figure` instance wrapping our plot. - - Notes - ----- - If you are creating many figures, make sure you explicitly call - :rc:`.pyplot.close` on the figures you are not using, because this will - enable pyplot to properly clean up the memory. - """ - fig = plt.figure(fig_options['fig_label']) - FIGURES[fig_options['fig_label']] = fig - if plot_type == 'bar' and 'width' not in plot_options: - n_allocators = len(allocators) - width = 1 / (n_allocators + 1) - plot_options['width'] = width - for i, allocator in enumerate(allocators): - y_data = _get_y_data(bench, - y_expression, - allocator, - perms, - stat='mean', - scale=scale) - - if plot_options.get('yerr', False): - plot_options['yerr'] = _get_y_data(bench, - y_expression, - allocator, - perms, - stat='std') - try: - plot_func = getattr(plt, plot_type) - except AttributeError: - print_debug(f'Unknown plot type: {plot_type}') - raise - - _x_data = x_data - if not fig_options['autoticks']: - _x_data = np.arange(1, len(x_data) + 1) - if plot_type == 'bar': - _x_data = _x_data + width / 2 + (i * plot_options['width']) - - plot_func(_x_data, - y_data, - label=allocator, - color=_get_alloc_color(bench, allocator), - **plot_options) - - if fig_options['legend']: - plt.legend(loc=fig_options['legend_pos']) - - if not fig_options['autoticks']: - plt.xticks(_x_data - (i / 2 * plot_options['width']), x_data) - - plt.xlabel(fig_options['xlabel']) - plt.ylabel(fig_options['ylabel']) - plt.title(fig_options['title']) - - fig_path = os.path.join(sumdir, f'{fig_options["fig_label"]}.{file_ext}') - if file_ext == 'tex': - import tikzplotlib - tikzplotlib.save(fig_path) - else: - fig.savefig(fig_path) - - return fig - -def plot(bench, - y_expression, - plot_type='errorbar', - x_args=None, - scale=None, - plot_options=None, - fig_options=None, - file_postfix="", - sumdir="", - file_ext=src.globalvars.summary_file_ext): - """ - Create plots for a given expression for the y axis. - - Parameters - ---------- - - y_expression : str - - plot_type : str, optional, default='errorbar' - The plot type for which the options should be created. - Possible values: {'bar', 'errorbar', 'plot'} - - x_args : [str], optional, default=None - The benchmark arguments for which a plot should be created. - If not provided, defaults to :rc:`bench.arguments.keys()` - - scale : str, optional, default=None - Name of the allocator which should be used to normalize the results. - - plot_options : dict, optional, default None - Dictionary containing plot options which should be passed to the plot - type function. If not provided the default plot type options are used. - Possible options: - * yerr: bool - Plot the standard deviation as errorbars - * marker: str - Style of the used markers - * line: str - Style of the drawn lines - - fig_options : dict, optional, default None - Dictionary containing figure options. - If not provided the default plot type options are used. - Possible options: - * ylabel : str - The label of the y axis. - * xlabel : str - The label of the x axis. - * title : str - The title of the plot. - * legend : bool - Should the plot have a legend. - * legend_pos : str - Location of the legend. - For possible values see :rc:`help(matplotlib.pyploy.legend)`. - * autoticks : bool - Let matplotlib set the xticks automatically. - - file_postfix: str, optional, default="" - Postfix which is appended to the plot's file name. - - sumdir : path or str, optional, default="" - Directory where the plot should be saved. If not provided defaults - to the current working directory. - - file_ext : str, optional, default=:rc:`src.globalvars.summary_file_ext` - File extension of the saved plot. If not provided defaults to the - value of :rc:`src.globalvars.summary_file_ext` - - """ - - args = bench.results["args"] - allocators = bench.results["allocators"] - - x_args = x_args or args - - for loose_arg in x_args: - x_data = args[loose_arg] - - fixed_args = [[(k, v) for v in args[k]] for k in args if k != loose_arg] - for fixed_part in itertools.product(*fixed_args): - fixed_part = {k:v for k, v in fixed_part} - - fixed_part_str = ".".join([f'{k}={v}' for k, v in fixed_part.items()]) - fig_label = f'{bench.name}.{fixed_part_str}.{file_postfix}' - - cur_plot_options = _create_plot_options(plot_type, **plot_options or {}) - - cur_fig_options = {} - - substitutions = vars() - substitutions.update(vars(bench)) - for option, value in (fig_options or {}).items(): - if isinstance(value, str): - cur_fig_options[option] = value.format(**substitutions) - - cur_fig_options = _create_figure_options(plot_type, fig_label, **cur_fig_options) - - # plot specific defaults - cur_fig_options.setdefault("ylabel", y_expression) - cur_fig_options.setdefault("xlabel", loose_arg) - cur_fig_options.setdefault("titel", fig_label) - - _plot(bench, - allocators, - y_expression, - x_data, - list(bench.iterate_args(args=args, fixed=fixed_part)), - plot_type, - cur_plot_options, - cur_fig_options) - -def print_common_facts(comment_symbol="", file=None): - print(comment_symbol, "Common facts:", file=file) - for fact, value in src.facter.FACTS.items(): - print(f"{comment_symbol} {fact}: {value}", file=file) - print(file=file) - -def print_facts(bench, comment_symbol="", print_common=True, print_allocators=False, file=None): - """Write collected facts about used system and benchmark to file""" - print(comment_symbol, bench.name, file=file) - print(file=file) - - if print_common: - print_common_facts(comment_symbol=comment_symbol, file=file) - - print(comment_symbol, "Benchmark facts:", file=file) - for fact, value in bench.results["facts"].items(): - print(comment_symbol, f"{fact}: {value}", file=file) - - if print_allocators: - print(comment_symbol, f'allocators: {" ".join(bench.results["allocators"])}', file=file) - - print(file=file) - - -def export_stats_to_csv(bench, datapoint, path=None): - """Write descriptive statistics about datapoint to csv file""" - allocators = bench.results["allocators"] - args = bench.results["args"] - stats = bench.results["stats"] - - if path is None: - path = datapoint - - path = path + ".csv" - - stats_fields = list(stats[list(allocators)[0]][list( - bench.iterate_args(args=args))[0]]) - fieldnames = ["allocator", *args, *stats_fields] - widths = [] - for fieldname in fieldnames: - widths.append(len(fieldname) + 2) - - # collect rows - rows = {} - for alloc in allocators: - rows[alloc] = {} - for perm in bench.iterate_args(args=args): - row = [] - row.append(alloc) - row += list(perm._asdict().values()) - row += [ - stats[alloc][perm][stat][datapoint] - for stat in stats[alloc][perm] - ] - row[-1] = (",".join([str(x) for x in row[-1]])) - rows[alloc][perm] = row - - # calc widths - for i in range(0, len(fieldnames)): - for alloc in allocators: - for perm in bench.iterate_args(args=args): - field_len = len(str(rows[alloc][perm][i])) + 2 - if field_len > widths[i]: - widths[i] = field_len - - with open(path, "w") as csv_file: - headerline = "" - for i, name in enumerate(fieldnames): - headerline += name.capitalize().ljust(widths[i]).replace("_", "-") - print(headerline, file=csv_file) - - for alloc in allocators: - for perm in bench.iterate_args(args=args): - line = "" - for i, row in enumerate(rows[alloc][perm]): - line += str(row).ljust(widths[i]) - print(line.replace("_", "-"), file=csv_file) - - -def export_stats_to_dataref(bench, datapoint, path=None): - """Write descriptive statistics about datapoint to dataref file""" - stats = bench.results["stats"] - - if path is None: - path = datapoint - - path = path + ".dataref" - - # Example: \drefset{/mysql/glibc/40/Lower-whisker}{71552.0} - line = "\\drefset{{/{}/{}/{}/{}}}{{{}}}" - - with open(path, "w") as dataref_file: - # Write facts to file - print_facts(bench, comment_symbol="%", file=dataref_file) - - for alloc in bench.results["allocators"]: - for perm in bench.iterate_args(args=bench.results["args"]): - for statistic, values in stats[alloc][perm].items(): - cur_line = line.format( - bench.name, alloc, - "/".join([str(p) for p in list(perm)]), statistic, - values.get(datapoint, nan)) - # Replace empty outliers - cur_line.replace("[]", "") - # Replace underscores - cur_line.replace("_", "-") - print(cur_line, file=dataref_file) - - -def write_best_doublearg_tex_table(bench, - expr, - sort=">", - file_postfix="", - sumdir=""): - args = bench.results["args"] - keys = list(args.keys()) - allocators = bench.results["allocators"] - - header_arg = keys[0] if len(args[keys[0]]) < len( - args[keys[1]]) else keys[1] - row_arg = [arg for arg in args if arg != header_arg][0] - - headers = args[header_arg] - rows = args[row_arg] - - cell_text = [] - for arg_value in rows: - row = [] - for perm in bench.iterate_args(args=args, fixed={row_arg: arg_value}): - best = [] - best_val = None - for allocator in allocators: - mean = _eval_with_stat(bench, expr, allocator, perm, "mean") - - if not best_val: - best = [allocator] - best_val = mean - elif ((sort == ">" and mean > best_val) - or (sort == "<" and mean < best_val)): - best = [allocator] - best_val = mean - elif mean == best_val: - best.append(allocator) - - row.append(f"{best[0]}: {best_val:.3f}") - cell_text.append(" & ".join(row)) - - table_layout = " l |" * len(headers) - header_line = " & ".join([str(x) for x in headers]) - cell_text = "\\\\\n".join(cell_text) - - tex =\ -f"""\\documentclass{{standalone}} -\\begin{{document}} -\\begin{{tabular}}{{|{table_layout}}} -{header_arg}/{row_arg} & {header_line} \\\\ -{cell_text} -\\end{{tabular}} -\\end{{document}} -""" - - fname = os.path.join(sumdir, f"{bench.name}.{file_postfix}.tex") - with open(fname, "w") as tex_file: - print(tex, file=tex_file) - - -def write_tex_table(bench, entries, file_postfix="", sumdir=""): - """generate a latex standalone table from an list of entries dictionaries - - Entries must have at least the two keys: "label" and "expression". - The optional "sort" key specifies the direction of the order: - ">" : bigger is better. - "<" : smaller is better. - - Table layout: - - | alloc1 | alloc2 | .... - --------------------------------------- - | name1 name2 | ... - --------------------------------------- - perm1 | eavl1 eval2 | ... - perm2 | eval1 eval2 | ... - """ - args = bench.results["args"] - allocators = bench.results["allocators"] - nallocators = len(allocators) - nentries = len(entries) - perm_fields = bench.Perm._fields - nperm_fields = len(perm_fields) - - alloc_header_line = f"\\multicolumn{{{nperm_fields}}}{{c|}}{{}} &" - for alloc in allocators: - alloc_header_line += f"\\multicolumn{{{nentries}}}{{c|}}{{{alloc}}} &" - alloc_header_line = alloc_header_line[:-1] + "\\\\" - - perm_fields_header = "" - for field in bench.Perm._fields: - perm_fields_header += f'{field} &' - entry_header_line = "" - for entry in entries: - entry_header_line += f'{entry["label"]} &' - entry_header_line = perm_fields_header + entry_header_line * nallocators - entry_header_line = entry_header_line[:-1] + "\\\\" - - fname = os.path.join(sumdir, ".".join([bench.name, file_postfix, "tex"])) - with open(fname, "w") as tex_file: - print("\\documentclass{standalone}", file=tex_file) - print("\\usepackage{booktabs}", file=tex_file) - print("\\usepackage{xcolor}", file=tex_file) - print("\\begin{document}", file=tex_file) - print("\\begin{tabular}{|", - f"{'c|'*nperm_fields}", - f"{'c'*nentries}|" * nallocators, - "}", - file=tex_file) - print("\\toprule", file=tex_file) - - print(alloc_header_line, file=tex_file) - print("\\hline", file=tex_file) - print(entry_header_line, file=tex_file) - print("\\hline", file=tex_file) - - for perm in bench.iterate_args(args=args): - values = [[] for _ in entries] - maxs = [None for _ in entries] - mins = [None for _ in entries] - for allocator in allocators: - for i, entry in enumerate(entries): - expr = entry["expression"] - values[i].append( - _eval_with_stat(bench, expr, allocator, perm, "mean")) - - # get max and min for each entry - for i, entry in enumerate(entries): - if not "sort" in entry: - continue - # bigger is better - if entry["sort"] == ">": - maxs[i] = max(values[i]) - mins[i] = min(values[i]) - # smaller is better - elif entry["sort"] == "<": - mins[i] = max(values[i]) - maxs[i] = min(values[i]) - - # build row - row = "" - perm_dict = perm._asdict() - for field in perm_fields: - row += str(perm_dict[field]) + "&" - - for i, _ in enumerate(allocators): - for j, entry_vals in enumerate(values): - val = entry_vals[i] - - # format - val_str = str(val) - if isinstance(val, float): - val_str = f"{val:.2f}" - - # colorize - if val == maxs[j]: - val_str = f"\\textcolor{{green}}{{{val_str}}}" - elif val == mins[j]: - val_str = f"\\textcolor{{red}}{{{val_str}}}" - row += f"{val_str} &" - #escape _ for latex - row = row.replace("_", "\\_") - print(row[:-1], "\\\\", file=tex_file) - - print("\\end{tabular}", file=tex_file) - print("\\end{document}", file=tex_file) - - -def pgfplot_legend(bench, - sumdir="", - file_name="pgfplot_legend", - colors=True, - columns=3): - """create a standalone pgfplot legend""" - - allocators = bench.results["allocators"] - color_definitions = "" - legend_entries = "" - for alloc_name, alloc_dict in allocators.items(): - if colors: - # define color - rgb = matplotlib.colors.to_rgb(_get_alloc_color(bench, alloc_dict)) - color_definitions += f"\\providecolor{{{alloc_name}-color}}{{rgb}}{{{rgb[0]},{rgb[1]},{rgb[2]}}}\n" - color_definitions += f"\\pgfplotsset{{{alloc_name}/.style={{color={alloc_name}-color}}}}\n\n" - - alloc_color = "" - if colors: - alloc_color = f"{alloc_name}-color" - legend_entries += f"\t\\addplot+ [{alloc_color}] coordinates {{(0,0)}};\n" - legend_entries += f"\t\\addlegendentry{{{alloc_name}}}\n\n" - - tex =\ -f""" -\\documentclass{{standalone}} -\\usepackage{{pgfplots}} - -\\usepackage{{xcolor}} - -{color_definitions} -{src.globalvars.latex_custom_preamble} -\\begin{{document}} -\\begin{{tikzpicture}} -\\begin{{axis}} [ -\tlegend columns={columns}, -\thide axis, -\tscale only axis, width=5mm, % make axis really small (smaller than legend) -] - -{legend_entries} -\\end{{axis}} -\\end{{tikzpicture}} -\\end{{document}}""" - - with open(os.path.join(sumdir, f"{file_name}.tex"), "w") as legend_file: - print(tex, file=legend_file) - - -def pgfplot(bench, - perms, - xexpr, - yexpr, - axis_attr="", - bar=False, - ylabel="y-label", - xlabel="x-label", - title="default title", - postfix="", - sumdir="", - scale=None, - error_bars=True, - colors=True): - - allocators = bench.results["allocators"] - perms = list(perms) - - label_substitutions = vars() - label_substitutions.update(vars(bench)) - xlabel = xlabel.format(**label_substitutions) - ylabel = ylabel.format(**label_substitutions) - title = title.format(**label_substitutions) - - if bar: - axis_attr = f"\tybar,\n{axis_attr}" - - color_definitions = "" - style_definitions = "" - plots = "" - for alloc_name, alloc_dict in allocators.items(): - if colors: - # define color - rgb = matplotlib.colors.to_rgb(_get_alloc_color(bench, alloc_dict)) - color_definitions += f"\\providecolor{{{alloc_name}-color}}{{rgb}}{{{rgb[0]},{rgb[1]},{rgb[2]}}}\n" - style_definitions += f"\\pgfplotsset{{{alloc_name}/.style={{color={alloc_name}-color}}}}\n\n" - - eb = "" - ebt = "" - edp = "" - if error_bars: - eb = ",\n\terror bars/.cd, y dir=both, y explicit,\n" - ebt += "[y error=error]" - edp = " error" - alloc_color = "" - if colors: - alloc_color = f"{alloc_name}" - plots += f"\\addplot+[{alloc_color}{eb}] table {ebt}" - - plots += f" {{\n\tx y{edp}\n" - - for perm in perms: - xval = _eval_with_stat(bench, xexpr, alloc_name, perm, "mean") - yval = _eval_with_stat(bench, yexpr, alloc_name, perm, "mean") - error = "" - if error_bars: - error = f" {_eval_with_stat(bench, yexpr, alloc_name, perm, 'std')}" - plots += f"\t{xval} {yval}{error}\n" - - plots += "};\n" - - tex =\ -f"""\\documentclass{{standalone}} -\\usepackage{{pgfplots}} -\\usepackage{{xcolor}} -{style_definitions} -% include commont.tex if found to override styles -% see https://tex.stackexchange.com/questions/377295/how-to-prevent-input-from-failing-if-the-file-is-missing/377312#377312 -\\InputIfFileExists{{common.tex}}{{}}{{}} -{color_definitions} -\\begin{{document}} -\\begin{{tikzpicture}} -\\begin{{axis}}[ -\ttitle={{{title}}}, -\txlabel={{{xlabel}}}, -\tylabel={{{ylabel}}}, -{axis_attr}] - -{plots} -\\end{{axis}} -\\end{{tikzpicture}} -\\end{{document}}""" - - with open(os.path.join(sumdir, f"{bench.name}.{postfix}.tex"), - "w") as plot_file: - print(tex, file=plot_file) diff --git a/src/print_status_on_exit.c b/src/print_status_on_exit.c deleted file mode 100644 index 5775afc..0000000 --- a/src/print_status_on_exit.c +++ /dev/null @@ -1,37 +0,0 @@ -#define _GNU_SOURCE -#include <dlfcn.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -static void print_status(void) -{ - char buf[4096]; - - FILE* status = fopen("/proc/self/status", "r"); - if (status == NULL) - { - perror("fopen status"); - exit(1); - } - - FILE* output = fopen("status", "a"); - if (output == NULL) - { - perror("fopen output file"); - exit(1); - } - - while (!feof(status)) - { - fgets(&buf[0], 4096, status); - fprintf(output, "%s", buf); - } - fclose(status); -} - -static void __attribute__((constructor)) init() -{ - atexit(print_status); -} - diff --git a/src/sig_handlers.c b/src/sig_handlers.c deleted file mode 100644 index 3274482..0000000 --- a/src/sig_handlers.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static void abnormal_termination_handler(int signo) { - psignal(signo, ""); - exit(signo); -} - -static void __attribute__((constructor)) register_handlers(void) -{ - struct sigaction sa, old_sa; - sa.sa_handler = abnormal_termination_handler; - sigemptyset(&sa.sa_mask); - - sigaction(SIGABRT, NULL, &old_sa); - if (old_sa.sa_handler == SIG_DFL) { - if (sigaction(SIGABRT, &sa, NULL) == -1) { - perror("sigaction"); - exit(1); - } - } else { - fprintf(stderr, "SIGABRT handler already set"); - } - - sigaction(SIGSEGV, NULL, &old_sa); - if (old_sa.sa_handler == SIG_DFL) { - if (sigaction(SIGSEGV, &sa, NULL) == -1) { - perror("sigaction"); - exit(1); - } - } else { - fprintf(stderr, "SIGSEGV handler already set"); - } -} - diff --git a/src/util.py b/src/util.py deleted file mode 100644 index fb0e75b..0000000 --- a/src/util.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> -# -# This file is part of allocbench. -# -# allocbench is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# allocbench is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with allocbench. If not, see <http://www.gnu.org/licenses/>. -"""Helper functions for allocbench""" - -import hashlib -import os -import subprocess -import sys - -import src.globalvars - - -def run_cmd(cmd, - output_verbosity=2, - capture=False, - shell=False, - check=True, - cwd=None, - input=None): - """subprocess.run wrapper which cares about the set verbosity""" - if capture: - stdout = subprocess.PIPE - stderr = stdout - elif src.globalvars.verbosity < output_verbosity: - stdout = subprocess.DEVNULL - stderr = stdout - else: - stdout = None - stderr = stdout - - print_debug(f"Running command {cmd}") - - return subprocess.run(cmd, - stdout=stdout, - stderr=stderr, - shell=shell, - check=check, - input=input, - cwd=cwd, - universal_newlines=True) - - -def is_exe(fpath): - """Check if the given path is an exexutable file""" - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - -def find_cmd(cmd): - """Return abspath of cmd if it is an executable or in PATH""" - fpath, _ = os.path.split(cmd) - - # Search for file - if fpath: - if is_exe(cmd): - return cmd - # Search in PATH - else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, cmd) - if is_exe(exe_file): - return exe_file - - return None - - -def prefix_cmd_with_abspath(cmd): - """Prefix cmd with the abspath of the first word - - Usefull if cmd should be executed by the loader of a custom glibc.""" - - if os.path.isabs(cmd) or cmd == "": - return cmd - - binary_end = cmd.find(" ") - binary_end = None if binary_end == -1 else binary_end - - binary_abspath = run_cmd(["whereis", cmd[0:binary_end]], - capture=True).stdout - binary_abspath = binary_abspath.split()[1] - - # add arguments of cmd to the abspath - if binary_end: - return binary_abspath + " " + cmd[binary_end:] - return binary_abspath - - -def allocbench_msg(color, *objects, sep=' ', end='\n', file=None): - """Colored output function wrapping print""" - if src.globalvars.verbosity < 0: - return - - color = { - "YELLOW": "\x1b[33m", - "GREEN": "\x1b[32m", - "RED": "\x1b[31m" - }[color] - - is_atty = sys.stdout.isatty() - if is_atty: - print(color, end="", file=file, flush=True) - - print(*objects, sep=sep, end=end, file=file) - - if is_atty: - print("\x1b[0m", end="", file=file, flush=True) - - -def print_debug(*objects, sep=' ', end='\n', file=None): - """Print colorless debug message""" - if src.globalvars.verbosity < 3: - return - print(*objects, sep=sep, end=end, file=file) - - -def print_info(*objects, sep=' ', end='\n', file=None): - """Print colorless info message""" - if src.globalvars.verbosity < 1: - return - print(*objects, sep=sep, end=end, file=file) - - -def print_info0(*objects, sep=' ', end='\n', file=None): - """Print colorless info message at every verbosity level message""" - if src.globalvars.verbosity < 0: - return - print(*objects, sep=sep, end=end, file=file) - - -def print_info2(*objects, sep=' ', end='\n', file=None): - """Print colorless info message at the second verbosity level message""" - if src.globalvars.verbosity < 2: - return - print(*objects, sep=sep, end=end, file=file) - - -def print_status(*objects, sep=' ', end='\n', file=None): - """Print green status message""" - allocbench_msg("GREEN", *objects, sep=sep, end=end, file=file) - - -def print_warn(*objects, sep=' ', end='\n', file=None): - """Print yellow warning""" - if src.globalvars.verbosity < 1: - return - allocbench_msg("YELLOW", *objects, sep=sep, end=end, file=file) - - -def print_error(*objects, sep=' ', end='\n', file=sys.stderr): - """Print red error message""" - allocbench_msg("RED", *objects, sep=sep, end=end, file=file) - - -def print_license_and_exit(): - """Print GPL info and Copyright before exit""" - print("Copyright (C) 2018-2019 Florian Fischer") - print( - "License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>") - sys.exit(0) - - -def sha1sum(filename): - """Return sha1sum of a file""" - sha1 = hashlib.sha1() - barray = bytearray(64 * 1024) - view = memoryview(barray) - with open(filename, 'rb', buffering=0) as f: - for n in iter(lambda: f.readinto(view), 0): - sha1.update(view[:n]) - return sha1.hexdigest() |
