summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-10-08 15:54:14 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2009-10-08 16:35:25 +0200
commit76f7b56c73ba495e38f79389de15d434b3f926bb (patch)
tree2f4220cf61ef710029d7f4f9b07a1dfd9a35658f
downloadptx-sisyphus-76f7b56c73ba495e38f79389de15d434b3f926bb.tar.gz
ptx-sisyphus-76f7b56c73ba495e38f79389de15d434b3f926bb.tar.xz
initial import
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--GNUmakefile.am34
-rwxr-xr-xautogen-oldtools.sh45
-rwxr-xr-xautogen.sh22
-rw-r--r--config/GNUmakefile.am8
-rw-r--r--config/m4/.secret-world-domination-project0
-rw-r--r--config/m4/acx_pthread.m4238
-rw-r--r--config/ptx-sisyphus.pc.in12
-rw-r--r--configure.ac135
-rw-r--r--include/GNUmakefile.am9
-rw-r--r--include/gettext.h9
-rw-r--r--include/ptx-sisyphusstuff.h5
-rw-r--r--src/GNUmakefile.am42
-rw-r--r--src/alignment.c46
-rw-r--r--src/context-switches.c190
-rw-r--r--src/ff_bench.c408
-rw-r--r--src/float_bench.c843
-rw-r--r--src/memxfer5b.c336
-rw-r--r--src/pi8.c316
-rw-r--r--src/timeout.c188
-rwxr-xr-xwizzard.sh35
20 files changed, 2921 insertions, 0 deletions
diff --git a/GNUmakefile.am b/GNUmakefile.am
new file mode 100644
index 0000000..7f8d6f8
--- /dev/null
+++ b/GNUmakefile.am
@@ -0,0 +1,34 @@
+SUBDIRS = \
+ include \
+ config \
+ src \
+ tests
+
+EXTRA_DIST = \
+ autogen.sh \
+ config/m4/.secret-world-domination-project
+
+MAINTAINERCLEANFILES = \
+ configure \
+ GNUmakefile.in \
+ aclocal.m4 \
+ config/autoconf/compile \
+ config/autoconf/config.guess \
+ config/autoconf/config.sub \
+ config/autoconf/depcomp \
+ config/autoconf/install-sh \
+ config/autoconf/ltmain.sh \
+ config/autoconf/mdate-sh \
+ config/autoconf/missing \
+ config/autoconf/texinfo.tex \
+ config/m4/libtool.m4 \
+ config/m4/ltoptions.m4 \
+ config/m4/ltsugar.m4 \
+ config/m4/ltversion.m4 \
+ config/m4/lt~obsolete.m4 \
+ $(DIST_ARCHIVES)
+
+maintainer-clean-local:
+ -chmod -R a+rw $(distdir)
+ -rm -fr $(distdir)
+
diff --git a/autogen-oldtools.sh b/autogen-oldtools.sh
new file mode 100755
index 0000000..cbb9522
--- /dev/null
+++ b/autogen-oldtools.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+#
+# usage:
+#
+# banner <target name>
+#
+banner() {
+
+ echo
+ TG=`echo $1 | sed -e "s,/.*/,,g"`
+ LINE=`echo $TG |sed -e "s/./-/g"`
+ echo $LINE
+ echo $TG
+ echo $LINE
+ echo
+}
+
+
+ACLOCAL=${ACLOCAL:=aclocal}
+AUTOHEADER=${AUTOHEADER:=autoheader}
+AUTOMAKE=${AUTOMAKE:=automake}
+AUTOCONF=${AUTOCONF:=autoconf}
+
+banner "running libtoolize"
+libtoolize --force
+[ $? != 0 ] && exit
+
+banner "running aclocal"
+$ACLOCAL -I config/m4
+[ $? != 0 ] && exit
+
+banner "running autoheader"
+$AUTOHEADER
+[ $? != 0 ] && exit
+
+banner "running automake"
+$AUTOMAKE --gnu --add-missing -Wall
+[ $? != 0 ] && exit
+
+banner "running autoconf"
+$AUTOCONF -Wall
+[ $? != 0 ] && exit
+
+banner "Finished"
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..29db9c9
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+#
+# usage:
+#
+# banner <target name>
+#
+banner() {
+ echo
+ TG=`echo $1 | sed -e "s,/.*/,,g"`
+ LINE=`echo $TG |sed -e "s/./-/g"`
+ echo $LINE
+ echo $TG
+ echo $LINE
+ echo
+}
+
+banner "autoreconf"
+
+autoreconf --force --install --symlink -Wall || exit $?
+
+banner "Finished"
diff --git a/config/GNUmakefile.am b/config/GNUmakefile.am
new file mode 100644
index 0000000..d3654cc
--- /dev/null
+++ b/config/GNUmakefile.am
@@ -0,0 +1,8 @@
+EXTRA_DIST = \
+ ptx-sisyphus.pc.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ptx-sisyphus.pc
+
+MAINTAINERCLEANFILES = \
+ GNUmakefile.in
diff --git a/config/m4/.secret-world-domination-project b/config/m4/.secret-world-domination-project
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/m4/.secret-world-domination-project
diff --git a/config/m4/acx_pthread.m4 b/config/m4/acx_pthread.m4
new file mode 100644
index 0000000..06af842
--- /dev/null
+++ b/config/m4/acx_pthread.m4
@@ -0,0 +1,238 @@
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl @summary figure out how to build C programs using POSIX threads
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl LIBS="$PTHREAD_LIBS $LIBS"
+dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2005-06-15
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+ if test x"$acx_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+ [attr_name=$attr; break])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/config/ptx-sisyphus.pc.in b/config/ptx-sisyphus.pc.in
new file mode 100644
index 0000000..e77e96a
--- /dev/null
+++ b/config/ptx-sisyphus.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: <name>
+Description: <description>
+Requires: @REQUIRES_LIBRN@
+Version: @VERSION@
+Libs: -L${libdir} -lptx-sisyphus
+#Libs.private: -lm -lpthread ...etc...
+Cflags: -I${includedir}
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..526ec42
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,135 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.59)
+
+AC_INIT([ptx-sisyphus], [0.0.0], [bugs@pengutronix.de])
+AC_CONFIG_HEADERS([include/ptx-sisyphus_config.h])
+AC_CONFIG_SRCDIR([src/ptx-sisyphus.c])
+AC_CONFIG_MACRO_DIR([config/m4])
+AC_CONFIG_AUX_DIR([config/autoconf])
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+AM_MAINTAINER_MODE
+
+CFLAGS="${CFLAGS} -Wall"
+
+#
+# libtool library versioning stuff
+#
+# Library code modified: REVISION++
+# Interfaces changed/added/removed: CURRENT++ REVISION=0
+# Interfaces added: AGE++
+# Interfaces removed: AGE=0
+LT_CURRENT=0
+LT_REVISION=0
+LT_AGE=0
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
+
+#
+# Checks for programs.
+#
+AC_PROG_CC
+#AM_MISSING_PROG(PERL, perl, $missing_dir)
+# libtool, old:
+AC_LIBTOOL_WIN32_DLL
+#AC_LIBTOOL_TAGS([])
+AC_PROG_LIBTOOL
+# libtool, new:
+# LT_INIT(win32-dll)
+
+AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2])
+
+
+#
+# Checks for libraries.
+#
+
+##
+# librn
+##
+# REQUIRES_LIBRN="librn >= 0.4.2"
+# AC_SUBST(REQUIRES_LIBRN)
+# PKG_CHECK_MODULES([librn],
+# [${REQUIRES_LIBRN}],
+# [],
+# [AC_MSG_ERROR([*** ${REQUIRES_LIBRN} not found by pkg-config on your system])]
+# )
+# AC_SUBST(librn_CFLAGS)
+# AC_SUBST(librn_LIBS)
+
+#
+# Checks for header files.
+#
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([ \
+ arpa/inet.h \
+ limits.h \
+ netdb.h \
+ netinet/in.h \
+ stddef.h \
+ stdlib.h \
+ string.h \
+ sys/param.h \
+ sys/socket.h \
+ sys/time.h \
+ sys/un.h \
+ unistd.h \
+ utime.h \
+ ])
+
+
+#
+# Checks for typedefs, structures, and compiler characteristics.
+#
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+
+
+#
+# Checks for library functions.
+#
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_FUNC_UTIME_NULL
+AC_CHECK_FUNCS([gethostbyaddr gethostbyname gethostname gettimeofday memset mkdir socket utime])
+
+
+#
+# Debugging
+#
+AC_MSG_CHECKING([whether to enable debugging])
+AC_ARG_ENABLE(debug,
+ AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=yes@:>@]),
+ [case "$enableval" in
+ y | yes) CONFIG_DEBUG=yes ;;
+ *) CONFIG_DEBUG=no ;;
+ esac],
+ [CONFIG_DEBUG=yes])
+AC_MSG_RESULT([${CONFIG_DEBUG}])
+if test "${CONFIG_DEBUG}" = "yes"; then
+ CFLAGS="${CFLAGS} -Werror -Wsign-compare -Wfloat-equal -Wformat-security -g -O1"
+ AC_DEFINE(DEBUG, 1, [debugging])
+else
+ CFLAGS="${CFLAGS} -O2"
+fi
+
+
+AC_CONFIG_FILES([
+ GNUmakefile
+ config/ptx-sisyphus.pc
+ config/GNUmakefile
+ include/GNUmakefile
+ src/GNUmakefile
+ tests/GNUmakefile
+ ])
+AC_OUTPUT
+
diff --git a/include/GNUmakefile.am b/include/GNUmakefile.am
new file mode 100644
index 0000000..30150f1
--- /dev/null
+++ b/include/GNUmakefile.am
@@ -0,0 +1,9 @@
+noinst_HEADERS = \
+ ptx-sisyphusstuff.h
+
+nobase_include_HEADERS = \
+ ptx-sisyphus.h
+
+MAINTAINERCLEANFILES = \
+ ptx-sisyphus_config.h.in \
+ GNUmakefile.in
diff --git a/include/gettext.h b/include/gettext.h
new file mode 100644
index 0000000..0565c9e
--- /dev/null
+++ b/include/gettext.h
@@ -0,0 +1,9 @@
+/* simple wrapper */
+#if ENABLE_NLS
+# include <libintl.h>
+# include <locale.h>
+# define _(string) gettext (string)
+#else
+# define _(string) (string)
+#endif
+
diff --git a/include/ptx-sisyphusstuff.h b/include/ptx-sisyphusstuff.h
new file mode 100644
index 0000000..91c4380
--- /dev/null
+++ b/include/ptx-sisyphusstuff.h
@@ -0,0 +1,5 @@
+#ifndef PTX-SISYPHUS_H
+#define PTX-SISYPHUS_H
+
+
+#endif
diff --git a/src/GNUmakefile.am b/src/GNUmakefile.am
new file mode 100644
index 0000000..9fbaa6f
--- /dev/null
+++ b/src/GNUmakefile.am
@@ -0,0 +1,42 @@
+lib_LTLIBRARIES = \
+ libptx-sisyphus.la
+
+bin_PROGRAMS = \
+ alignment \
+ context-switches \
+ ff_bench \
+ float_bench \
+ pi_int \
+ pi_fpu \
+ memxfer
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include
+
+float_bench_SOURCES = \
+ float_bench.c
+float_bench_LDADD = -lm
+
+ff_bench_SOURCES = \
+ ff_bench.c
+ff_bench_LDADD = -lm
+
+pi_int_SOURCES = \
+ pi8.c
+
+pi_fpu_SOURCES = \
+ pi8.c
+pi_fpu_CPPFLAGS = -DUSEFPU
+
+alignment_SOURCES = \
+ alignment.c
+
+context_switches_SOURCES = \
+ context-switches.c
+
+timeout_SOURCES = \
+ timeout.c
+
+MAINTAINERCLEANFILES = \
+ GNUmakefile.in
diff --git a/src/alignment.c b/src/alignment.c
new file mode 100644
index 0000000..4b0cb81
--- /dev/null
+++ b/src/alignment.c
@@ -0,0 +1,46 @@
+/*
+ * Simple tool to check if unaligned accesses to memory work
+ * as expected
+ *
+ * Copyleft 2009 Sascha Hauer, <s.hauer@pengutronix.de>
+ *
+ *
+ * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ * Version 2, December 2004
+ *
+ * Copyright (C) 2004 Sam Hocevar
+ * 14 rue de Plaisance, 75014 Paris, France
+ * Everyone is permitted to copy and distribute verbatim or modified
+ * copies of this license document, and changing it is allowed as long
+ * as the name is changed.
+ *
+ * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+ *
+ * 0. You just DO WHAT THE FUCK YOU WANT TO.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void)
+{
+ char space[sizeof(unsigned int)];
+ char *s = space;
+ unsigned int *unaligned;
+ int aligned1 = 0xdeadbeef, aligned2;
+
+ unaligned = (unsigned int *)(s + 1);
+
+ *unaligned = aligned1;
+ aligned2 = *unaligned;
+
+ if (aligned1 != aligned2) {
+ fprintf(stderr, "unaligned access failed (0x%08x != 0x%08x)\n",
+ aligned1, aligned2);
+ exit(1);
+ }
+
+ exit(0);
+}
+
diff --git a/src/context-switches.c b/src/context-switches.c
new file mode 100644
index 0000000..27a4d60
--- /dev/null
+++ b/src/context-switches.c
@@ -0,0 +1,190 @@
+/*
+ * This is a simple tool to measure the amount of context switches on
+ * a system in a specific period of time.
+ * It can be used to detect changes in the kernel/scheduler that change
+ * systems behaviour over the time of development
+ *
+ * Its intended for automated usage, so it does no human readable output.
+ *
+ * It terminates in to ways: By absolute time or by turns of 1 seconds.
+ * It can output the measured context switches one value per turn or as two
+ * values (min max) when it is going to terminate.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <ptx-sisyphus_config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <time.h>
+#include <gettext.h>
+
+static int read_one_string(FILE *fd, char *buffer)
+{
+ int c;
+
+ while (1) {
+ c = fgetc(fd);
+ if (c == EOF || isspace(c)) {
+ *buffer = '\0';
+ break;
+ }
+ *buffer++ = c;
+ };
+
+ return c == EOF ? 1 : 0;
+}
+
+static unsigned long read_taskswitches(FILE *fd)
+{
+ char buffer[100];
+ int rc;
+
+ /* search for the string 'ctxt', the next value is the one we need */
+ do {
+ rc = read_one_string(fd, buffer);
+ if (!strcmp(buffer, "ctxt")) {
+ rc = read_one_string(fd, buffer);
+ break;
+ }
+ } while (rc == 0);
+
+ if (rc != 0)
+ return -1;
+
+ return strtoul(buffer, NULL, 10);
+}
+
+static int do_the_job(const char *statf, int job_time, int iterations, int collect)
+{
+ FILE *fd;
+ unsigned long min, max, last_val, current_val, diff_val;
+ int rc;
+ struct timespec tp_start, tp_current;
+
+ /* check if the file exists */
+ fd = fopen(statf, "r");
+ if (fd == NULL) {
+ fprintf(stderr, _("Cannot open status file '%s'\n"), statf);
+ return 1;
+ }
+
+ if (job_time != -1) {
+ rc = clock_gettime(CLOCK_MONOTONIC , &tp_start);
+ if (rc == -1) {
+ fprintf(stderr, _("Cannot read monotonic time stamp.\n"));
+ return 1;
+ }
+ }
+
+ min = -1;
+ max = 0UL;
+ last_val = read_taskswitches(fd);
+ fclose(fd);
+ if (last_val == -1) {
+ fprintf(stderr, _("Failure while reading content of '%s'\n"), statf);
+ return 1;
+ }
+
+ while (1) {
+ sleep(1);
+ fd = fopen(statf, "r");
+ current_val = read_taskswitches(fd);
+ fclose(fd);
+ if (last_val == -1) {
+ fprintf(stderr, _("Failure while reading content of '%s'\n"), statf);
+ return 1;
+ }
+ if (current_val < last_val) {
+ fprintf(stderr, _("Counter overrun. Please run again"));
+ return -1;
+ }
+
+ diff_val = current_val - last_val;
+ last_val = current_val;
+
+ if (max < diff_val)
+ max = diff_val;
+ if (min > diff_val)
+ min = diff_val;
+
+ if (collect == 0)
+ printf("%lu\n", diff_val);
+
+ /* check if we have to terminate the loop */
+ if (iterations > 0) {
+ iterations--;
+ if (iterations == 0)
+ break;
+ }
+ if (job_time != -1) {
+ rc = clock_gettime(CLOCK_MONOTONIC , &tp_current);
+ if (tp_current.tv_sec - tp_start.tv_sec >= job_time)
+ break;
+ }
+ };
+
+ if (collect != 0)
+ printf("%lu %lu\n", min, max);
+
+ return 0;
+}
+
+static void print_usage(const char *pname)
+{
+ printf(_("Usage is\n %s [options]\n"), pname);
+ printf(_("Optional [options] are:\n"));
+ printf(_(" -s time\n Defines the whole time this programm should run in seconds\n"));
+ printf(_(" -t turns\n Iteration count, with 1 second pause between each iteration\n"));
+ printf(_(" -c\n Collect all measurements and output one min/max pair at the end\n"));
+ printf(_(" -h\n This help text\n"));
+ printf(_(" -v\n Output version and terminate\n"));
+ printf(_("Default is no time limit, 10 iterations, no collection\n"));
+ printf(_("Send bugs to '%s'\n"), PACKAGE_BUGREPORT);
+}
+
+int main(int argc, char *argv[])
+{
+ int c, job_time = -1, iterations = -1, collect = 0;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+#endif
+
+ while (1) {
+ c = getopt(argc, argv, "s:t:hvc");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 't':
+ iterations = atoi(optarg);
+ break;
+ case 's':
+ job_time = atoi(optarg);
+ break;
+ case 'c':
+ collect = 1;
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ exit(0);
+ case 'v':
+ printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ exit(0);
+ }
+ }
+
+ c = do_the_job("/proc/stat", job_time, iterations, collect);
+
+ return c;
+}
diff --git a/src/ff_bench.c b/src/ff_bench.c
new file mode 100644
index 0000000..69357ca
--- /dev/null
+++ b/src/ff_bench.c
@@ -0,0 +1,408 @@
+/*
+
+ Two-dimensional FFT benchmark
+
+ Designed and implemented by John Walker in April of 1989.
+
+ This benchmark executes a specified number of passes (default
+ 20) through a loop in which each iteration performs a fast
+ Fourier transform of a square matrix (default size 256x256) of
+ complex numbers (default precision double), followed by the
+ inverse transform. After all loop iterations are performed
+ the results are checked against known correct values.
+
+ This benchmark is intended for use on C implementations which
+ define "int" as 32 bits or longer and permit allocation and
+ direct addressing of arrays larger than one megabyte.
+
+ If CAPOUT is defined, the result after all iterations is
+ written as a CA Lab pattern file. This is intended for
+ debugging in case horribly wrong results are obtained on a
+ given machine.
+
+ Archival timings are run with the definitions below set as
+ follows: Float = double, Asize = 256, Passes = 20, CAPOUT not
+ defined.
+
+ Time (seconds) System
+
+ 2393.93 Sun 3/260, SunOS 3.4, C, "-f68881 -O".
+ (John Walker).
+
+ 1928 Macintosh IIx, MPW C 3.0, "-mc68020
+ -mc68881 -elems881 -m". (Hugh Hoover).
+
+ 1636.1 Sun 4/110, "cc -O3 -lm". (Michael McClary).
+ The suspicion is that this is software
+ floating point.
+
+ 1556.7 Macintosh II, A/UX, "cc -O -lm"
+ (Michael McClary).
+
+ 1388.8 Sun 386i/250, SunOS 4.0.1 C
+ "-O /usr/lib/trig.il". (James Carrington).
+
+ 1331.93 Sun 3/60, SunOS 4.0.1, C,
+ "-O4 -f68881 /usr/lib/libm.il"
+ (Bob Elman).
+
+ 1204.0 Apollo Domain DN4000, C, "-cpu 3000 -opt 4".
+ (Sam Crupi).
+
+ 1174.66 Compaq 386/25, SCO Xenix 386 C.
+ (Peter Shieh).
+
+ 1068 Compaq 386/25, SCO Xenix 386,
+ Metaware High C. (Robert Wenig).
+
+ 1064.0 Sun 3/80, SunOS 4.0.3 Beta C
+ "-O3 -f68881 /usr/lib/libm.il". (James Carrington).
+
+ 1061.4 Compaq 386/25, SCO Xenix, High C 1.4.
+ (James Carrington).
+
+ 1059.79 Compaq 386/25, 387/25, High C 1.4,
+ DOS|Extender 2.2, 387 inline code
+ generation. (Nathan Bender).
+
+ 777.14 Compaq 386/25, IIT 3C87-25 (387 Compatible),
+ High C 1.5, DOS|Extender 2.2, 387 inline
+ code generation. (Nathan Bender).
+
+ 751 Compaq DeskPro 386/33, High C 1.5 + DOS|Extender,
+ 387 code generation. (James Carrington).
+
+ 431.44 Compaq 386/25, Weitek 3167-25, DOS 3.31,
+ High C 1.4, DOS|Extender, Weitek code generation.
+ (Nathan Bender).
+
+ 344.9 Compaq 486/25, Metaware High C 1.6, Phar Lap
+ DOS|Extender, in-line floating point. (Nathan
+ Bender).
+
+ 324.2 Data General Motorola 88000, 16 Mhz, Gnu C.
+
+ 323.1 Sun 4/280, C, "-O4". (Eric Hill).
+
+ 254 Compaq SystemPro 486/33, High C 1.5 + DOS|Extender,
+ 387 code generation. (James Carrington).
+
+ 242.8 Silicon Graphics Personal IRIS, MIPS R2000A,
+ 12.5 Mhz, "-O3" (highest level optimisation).
+ (Mike Zentner).
+
+ 233.0 Sun SPARCStation 1, C, "-O4", SunOS 4.0.3.
+ (Nathan Bender).
+
+ 187.30 DEC PMAX 3100, MIPS 2000 chip.
+ (Robert Wenig).
+
+ 120.46 Sun SparcStation 2, C, "-O4", SunOS 4.1.1.
+ (John Walker).
+
+ 120.21 DEC 3MAX, MIPS 3000, "-O4".
+
+ 98.0 Intel i860 experimental environment,
+ OS/2, data caching disabled. (Kern
+ Sibbald).
+
+ 34.9 Silicon Graphics Indigo², MIPS R4400,
+ 175 Mhz, IRIX 5.2, "-O".
+
+ 32.4 Pentium 133, Windows NT, Microsoft Visual
+ C++ 4.0.
+
+ 17.25 Silicon Graphics Indigo², MIPS R4400,
+ 175 Mhz, IRIX 6.5, "-O3".
+
+ 14.10 Dell Dimension XPS R100, Pentium II 400 MHz,
+ Windows 98, Microsoft Visual C 5.0.
+
+ 10.7 Hewlett-Packard Kayak XU 450Mhz Pentium II,
+ Microsoft Visual C++ 6.0, Windows NT 4.0sp3. (Nathan Bender).
+
+ 5.09 Sun Ultra 2, UltraSPARC V9, 300 MHz, gcc -O3.
+
+ 0.846 Dell Inspiron 9100, Pentium 4, 3.4 GHz, gcc -O3.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <math.h>
+
+/* The program may be run with Float defined as either float or
+ double. With IEEE arithmetic, the same answers are generated for
+ either floating point mode. */
+
+#define Float double /* Floating point type used in FFT */
+
+#define Asize 256 /* Array edge size */
+#define Passes 20 /* Number of FFT/Inverse passes */
+
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<=(b)?(a):(b))
+
+#define FWMODE "w"
+
+/*
+
+ Multi-dimensional fast Fourier transform
+
+ Adapted from Press et al., "Numerical Recipes in C".
+
+*/
+
+#define SWAP(a,b) tempr=(a); (a)=(b); (b)=tempr
+
+static void fourn(Float data[], int nn[], int ndim, int isign)
+{
+ int i1, i2, i3;
+ int i2rev, i3rev, ip1, ip2, ip3, ifp1, ifp2;
+ int ibit, idim, k1, k2, n, nprev, nrem, ntot;
+ Float tempi, tempr;
+ double theta, wi, wpi, wpr, wr, wtemp;
+
+ ntot = 1;
+ for (idim = 1; idim <= ndim; idim++)
+ ntot *= nn[idim];
+ nprev = 1;
+ for (idim = ndim; idim >= 1; idim--) {
+ n = nn[idim];
+ nrem = ntot / (n * nprev);
+ ip1 = nprev << 1;
+ ip2 = ip1 * n;
+ ip3 = ip2 * nrem;
+ i2rev = 1;
+ for (i2 = 1; i2 <= ip2; i2 += ip1) {
+ if (i2 < i2rev) {
+ for (i1 = i2; i1 <= i2 + ip1 - 2; i1 += 2) {
+ for (i3 = i1; i3 <= ip3; i3 += ip2) {
+ i3rev = i2rev + i3 - i2;
+ SWAP(data[i3], data[i3rev]);
+ SWAP(data[i3 + 1], data[i3rev + 1]);
+ }
+ }
+ }
+ ibit = ip2 >> 1;
+ while (ibit >= ip1 && i2rev > ibit) {
+ i2rev -= ibit;
+ ibit >>= 1;
+ }
+ i2rev += ibit;
+ }
+ ifp1 = ip1;
+ while (ifp1 < ip2) {
+ ifp2 = ifp1 << 1;
+ theta = isign * 6.28318530717959 / (ifp2 / ip1);
+ wtemp = sin(0.5 * theta);
+ wpr = -2.0 * wtemp * wtemp;
+ wpi = sin(theta);
+ wr = 1.0;
+ wi = 0.0;
+ for (i3 = 1; i3 <= ifp1; i3 += ip1) {
+ for (i1 = i3; i1 <= i3 + ip1 - 2; i1 += 2) {
+ for (i2 = i1; i2 <= ip3; i2 += ifp2) {
+ k1 = i2;
+ k2 = k1 + ifp1;
+ tempr = wr * data[k2] - wi * data[k2 + 1];
+ tempi = wr * data[k2 + 1] + wi * data[k2];
+ data[k2] = data[k1] - tempr;
+ data[k2 + 1] = data[k1 + 1] - tempi;
+ data[k1] += tempr;
+ data[k1 + 1] += tempi;
+ }
+ }
+ wr = (wtemp = wr) * wpr - wi * wpi + wr;
+ wi = wi * wpr + wtemp * wpi + wi;
+ }
+ ifp1 = ifp2;
+ }
+ nprev *= n;
+ }
+}
+#undef SWAP
+
+static void usage(const char *prg, FILE *out)
+{
+ fprintf(out, "usage: %s [options]\n", prg);
+ fprintf(out, " options are:\n");
+ fprintf(out, " '-d value' calculate a dimension of (value * value). Default is (256 * 256)\n");
+ fprintf(out, " '-p value' passes. Default is 20\n");
+ fprintf(out, " '-v' print program version and exit\n");
+ fprintf(out, " '-h' print this help and exit\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int i, j, k, l, m, npasses = Passes, faedge = Asize, c, ret;
+ Float *fdata;
+ static int nsize[] = {0, 0, 0};
+ long fanum, fasize;
+ double mapbase, mapscale, rmin, rmax, imin, imax;
+ struct timeval begin_tv, end_tv, diff_tv;
+
+ /* handle command line options first */
+ while (1) {
+ c = getopt(argc, argv, "d:p:hv");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ faedge = atoi(optarg); /* FFT array edge size */
+ break;
+ case 'p':
+ npasses = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0], stdout);
+ exit(0);
+ case 'v':
+ printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ exit(0);
+ }
+ }
+
+ /* now we start. Get the current time */
+ gettimeofday(&begin_tv, NULL);
+
+ fanum = faedge * faedge; /* Elements in FFT array */
+ fasize = ((fanum + 1) * 2 * sizeof(Float)); /* FFT array size */
+ nsize[1] = nsize[2] = faedge;
+
+ fdata = (Float *) malloc(fasize);
+ if (fdata == NULL) {
+ fprintf(stderr, "Can't allocate data array.\n");
+ exit(1);
+ }
+
+ /* Generate data array to process. */
+
+#define Re(x,y) fdata[1 + (faedge * (x) + (y)) * 2]
+#define Im(x,y) fdata[2 + (faedge * (x) + (y)) * 2]
+
+ memset(fdata, 0, fasize);
+ for (i = 0; i < faedge; i++) {
+ for (j = 0; j < faedge; j++) {
+ if (((i & 15) == 8) || ((j & 15) == 8))
+ Re(i, j) = 128.0;
+ }
+ }
+
+ for (i = 0; i < npasses; i++) {
+ /* Transform image to frequency domain. */
+ fourn(fdata, nsize, 2, 1);
+
+ /* Back-transform to image. */
+ fourn(fdata, nsize, 2, -1);
+ }
+
+ {
+ double r, ij, ar, ai;
+ rmin = 1e10; rmax = -1e10;
+ imin = 1e10; imax = -1e10;
+ ar = 0;
+ ai = 0;
+
+ for (i = 1; i <= fanum; i += 2) {
+ r = fdata[i];
+ ij = fdata[i + 1];
+ ar += r;
+ ai += ij;
+ rmin = min(r, rmin);
+ rmax = max(r, rmax);
+ imin = min(ij, imin);
+ imax = max(ij, imax);
+ }
+#ifdef DEBUG
+ printf("Real min %.4g, max %.4g. Imaginary min %.4g, max %.4g.\n",
+ rmin, rmax, imin, imax);
+ printf("Average real %.4g, imaginary %.4g.\n",
+ ar / fanum, ai / fanum);
+#endif
+ mapbase = rmin;
+ mapscale = 255 / (rmax - rmin);
+ }
+
+ /* See if we got the right answers. */
+
+ m = 0;
+ for (i = 0; i < faedge; i++) {
+ for (j = 0; j < faedge; j++) {
+ k = (Re(i, j) - mapbase) * mapscale;
+ l = (((i & 15) == 8) || ((j & 15) == 8)) ? 255 : 0;
+ if (k != l) {
+ m++;
+ fprintf(stderr,
+ "Wrong answer at (%d,%d)! Expected %d, got %d.\n",
+ i, j, l, k);
+ }
+ }
+ }
+ if (m == 0) {
+ fprintf(stderr, "%d passes. No errors in results.\n", npasses);
+ ret = 0;
+ } else {
+ fprintf(stderr, "%d passes. %d errors in results.\n",
+ npasses, m);
+ ret = 1;
+ }
+
+#ifdef CAPOUT
+
+ /* Output the result of the transform as a CA Lab pattern
+ file for debugging. */
+
+ {
+#define SCRX 322
+#define SCRY 200
+#define SCRN (SCRX * SCRY)
+ unsigned char patarr[SCRY][SCRX];
+ FILE *fp;
+
+/* Map user external state numbers to internal state index */
+
+#define UtoI(x) (((((x) >> 1) & 0x7F) | ((x) << 7)) & 0xFF)
+
+ /* Copy data from FFT buffer to map. */
+
+ memset(patarr, 0, sizeof patarr);
+ l = (SCRX - faedge) / 2;
+ m = (faedge > SCRY) ? 0 : ((SCRY - faedge) / 2);
+ for (i = 1; i < faedge; i++) {
+ for (j = 0; j < min(SCRY, faedge); j++) {
+ k = (Re(i, j) - mapbase) * mapscale;
+ patarr[j + m][i + l] = UtoI(k);
+ }
+ }
+
+ /* Dump pattern map to file. */
+
+ fp = fopen("fft.cap", "w");
+ if (fp == NULL) {
+ fprintf(stderr, "Cannot open output file.\n");
+ exit(0);
+ }
+ putc(':', fp);
+ putc(1, fp);
+ fwrite(patarr, SCRN, 1, fp);
+ putc(6, fp);
+ fclose(fp);
+ }
+#endif
+
+ gettimeofday(&end_tv, NULL);
+ timersub(&end_tv, &begin_tv, &diff_tv);
+
+ printf("Time(s): %u.%u\n", diff_tv.tv_sec, diff_tv.tv_usec);
+
+ return ret;
+}
diff --git a/src/float_bench.c b/src/float_bench.c
new file mode 100644
index 0000000..a415173
--- /dev/null
+++ b/src/float_bench.c
@@ -0,0 +1,843 @@
+/*
+
+ John Walker's Floating Point Benchmark, derived from...
+
+ Marinchip Interactive Lens Design System
+
+ John Walker December 1980
+
+ By John Walker
+ http://www.fourmilab.ch/
+
+ This program may be used, distributed, and modified freely as
+ long as the origin information is preserved.
+
+ This is a complete optical design raytracing algorithm,
+ stripped of its user interface and recast into portable C. It
+ not only determines execution speed on an extremely floating
+ point (including trig function) intensive real-world
+ application, it checks accuracy on an algorithm that is
+ exquisitely sensitive to errors. The performance of this
+ program is typically far more sensitive to changes in the
+ efficiency of the trigonometric library routines than the
+ average floating point program.
+
+ The benchmark may be compiled in two modes. If the symbol
+ INTRIG is defined, built-in trigonometric and square root
+ routines will be used for all calculations. Timings made with
+ INTRIG defined reflect the machine's basic floating point
+ performance for the arithmetic operators. If INTRIG is not
+ defined, the system library <math.h> functions are used.
+ Results with INTRIG not defined reflect the system's library
+ performance and/or floating point hardware support for trig
+ functions and square root. Results with INTRIG defined are a
+ good guide to general floating point performance, while
+ results with INTRIG undefined indicate the performance of an
+ application which is math function intensive.
+
+ Special note regarding errors in accuracy: this program has
+ generated numbers identical to the last digit it formats and
+ checks on the following machines, floating point
+ architectures, and languages:
+
+ Marinchip 9900 QBASIC IBM 370 double-precision (REAL * 8) format
+
+ IBM PC / XT / AT Lattice C IEEE 64 bit, 80 bit temporaries
+ High C same, in line 80x87 code
+ BASICA "Double precision"
+ Quick BASIC IEEE double precision, software routines
+
+ Sun 3 C IEEE 64 bit, 80 bit temporaries,
+ in-line 68881 code, in-line FPA code.
+
+ MicroVAX II C Vax "G" format floating point
+
+ Macintosh Plus MPW C SANE floating point, IEEE 64 bit format
+ implemented in ROM.
+
+ Inaccuracies reported by this program should be taken VERY
+ SERIOUSLY INDEED, as the program has been demonstrated to be
+ invariant under changes in floating point format, as long as
+ the format is a recognised double precision format. If you
+ encounter errors, please remember that they are just as likely
+ to be in the floating point editing library or the
+ trigonometric libraries as in the low level operator code.
+
+ The benchmark assumes that results are basically reliable, and
+ only tests the last result computed against the reference. If
+ you're running on a suspect system you can compile this
+ program with ACCURACY defined. This will generate a version
+ which executes as an infinite loop, performing the ray trace
+ and checking the results on every pass. All incorrect results
+ will be reported.
+
+ Representative timings are given below. All have been
+ normalised as if run for 1000 iterations.
+
+ Time in seconds Computer, Compiler, and notes
+ Normal INTRIG
+
+ 3466.00 4031.00 Commodore 128, 2 Mhz 8510 with software floating
+ point. Abacus Software/Data-Becker Super-C 128,
+ version 3.00, run in fast (2 Mhz) mode. Note:
+ the results generated by this system differed
+ from the reference results in the 8th to 10th
+ decimal place.
+
+ 3290.00 IBM PC/AT 6 Mhz, Microsoft/IBM BASICA version A3.00.
+ Run with the "/d" switch, software floating point.
+
+ 2131.50 IBM PC/AT 6 Mhz, Lattice C version 2.14, small model.
+ This version of Lattice compiles subroutine
+ calls which either do software floating point
+ or use the 80x87. The machine on which I ran
+ this had an 80287, but the results were so bad
+ I wonder if it was being used.
+
+ 1598.00 Macintosh Plus, MPW C, SANE Software floating point.
+
+ 1582.13 Marinchip 9900 2 Mhz, QBASIC compiler with software
+ floating point. This was a QBASIC version of the
+ program which contained the identical algorithm.
+
+ 404.00 IBM PC/AT 6 Mhz, Microsoft QuickBASIC version 2.0.
+ Software floating point.
+
+ 165.15 IBM PC/AT 6 Mhz, Metaware High C version 1.3, small
+ model. This was compiled to call subroutines for
+ floating point, and the machine contained an 80287
+ which was used by the subroutines.
+
+ 143.20 Macintosh II, MPW C, SANE calls. I was unable to
+ determine whether SANE was using the 68881 chip or
+ not.
+
+ 121.80 Sun 3/160 16 Mhz, Sun C. Compiled with -fsoft switch
+ which executes floating point in software.
+
+ 78.78 110.11 IBM RT PC (Model 6150). IBM AIX 1.0 C compiler
+ with -O switch.
+
+ 75.2 254.0 Microsoft Quick C 1.0, in-line 8087 instructions,
+ compiled with 80286 optimisation on. (Switches
+ were -Ol -FPi87-G2 -AS). Small memory model.
+
+ 69.50 IBM PC/AT 6Mhz, Borland Turbo BASIC 1.0. Compiled
+ in "8087 required" mode to generate in-line
+ code for the math coprocessor.
+
+ 66.96 IBM PC/AT 6Mhz, Microsoft QuickBASIC 4.0. This
+ release of QuickBASIC compiles code for the
+ 80287 math coprocessor.
+
+ 66.36 206.35 IBM PC/AT 6Mhz, Metaware High C version 1.3, small
+ model. This was compiled with in-line code for the
+ 80287 math coprocessor. Trig functions still call
+ library routines.
+
+ 63.07 220.43 IBM PC/AT, 6Mhz, Borland Turbo C, in-line 8087 code,
+ small model, word alignment, no stack checking,
+ 8086 code mode.
+
+ 17.18 Apollo DN-3000, 12 Mhz 68020 with 68881, compiled
+ with in-line code for the 68881 coprocessor.
+ According to Apollo, the library routines are chosen
+ at runtime based on coprocessor presence. Since the
+ coprocessor was present, the library is supposed to
+ use in-line floating point code.
+
+ 15.55 27.56 VAXstation II GPX. Compiled and executed under
+ VAX/VMS C.
+
+ 15.14 37.93 Macintosh II, Unix system V. Green Hills 68020
+ Unix compiler with in-line code for the 68881
+ coprocessor (-O -ZI switches).
+
+ 12.69 Sun 3/160 16 Mhz, Sun C. Compiled with -fswitch,
+ which calls a subroutine to select the fastest
+ floating point processor. This was using the 68881.
+
+ 11.74 26.73 Compaq Deskpro 386, 16 Mhz 80386 with 16 Mhz 80387.
+ Metaware High C version 1.3, compiled with in-line
+ for the math coprocessor (but not optimised for the
+ 80386/80387). Trig functions still call library
+ routines.
+
+ 8.43 30.49 Sun 3/160 16 Mhz, Sun C. Compiled with -f68881,
+ generating in-line MC68881 instructions. Trig
+ functions still call library routines.
+
+ 6.29 25.17 Sun 3/260 25 Mhz, Sun C. Compiled with -f68881,
+ generating in-line MC68881 instructions. Trig
+ functions still call library routines.
+
+ 4.57 Sun 3/260 25 Mhz, Sun FORTRAN 77. Compiled with
+ -O -f68881, generating in-line MC68881 instructions.
+ Trig functions are compiled in-line. This used
+ the FORTRAN 77 version of the program, FBFORT77.F.
+
+ 4.00 14.20 Sun386i/25 Mhz model 250, Sun C compiler.
+
+ 4.00 14.00 Sun386i/25 Mhz model 250, Metaware C.
+
+ 3.10 12.00 Compaq 386/387 25 Mhz running SCO Xenix 2.
+ Compiled with Metaware HighC 386, optimized
+ for 386.
+
+ 3.00 12.00 Compaq 386/387 25MHZ optimized for 386/387.
+
+ 2.96 5.17 Sun 4/260, Sparc RISC processor. Sun C,
+ compiled with the -O2 switch for global
+ optimisation.
+
+ 2.47 COMPAQ 486/25, secondary cache disabled, High C,
+ 486/387, inline f.p., small memory model.
+
+ 2.20 3.40 Data General Motorola 88000, 16 Mhz, Gnu C.
+
+ 1.56 COMPAQ 486/25, 128K secondary cache, High C, 486/387,
+ inline f.p., small memory model.
+
+ 0.66 1.50 DEC Pmax, Mips processor.
+
+ 0.63 0.91 Sun SparcStation 2, Sun C (SunOS 4.1.1) with
+ -O4 optimisation and "/usr/lib/libm.il" inline
+ floating point.
+
+ 0.60 1.07 Intel 860 RISC processor, 33 Mhz, Greenhills
+ C compiler.
+
+ 0.40 0.90 Dec 3MAX, MIPS 3000 processor, -O4.
+
+ 0.31 0.90 IBM RS/6000, -O.
+
+ 0.1129 0.2119 Dell Dimension XPS P133c, Pentium 133 MHz,
+ Windows 95, Microsoft Visual C 5.0.
+
+ 0.0883 0.2166 Silicon Graphics Indigo², MIPS R4400,
+ 175 Mhz, "-O3".
+
+ 0.0351 0.0561 Dell Dimension XPS R100, Pentium II 400 MHz,
+ Windows 98, Microsoft Visual C 5.0.
+
+ 0.0312 0.0542 Sun Ultra 2, UltraSPARC V9, 300 MHz, Solaris
+ 2.5.1.
+
+ 0.00862 0.01074 Dell Inspiron 9100, Pentium 4, 3.4 GHz, gcc -O3.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#ifndef INTRIG
+#include <math.h>
+#endif
+
+#define cot(x) (1.0 / tan(x))
+
+#define TRUE 1
+#define FALSE 0
+
+#define max_surfaces 10
+
+/* Local variables */
+
+/* static char tbfr[132]; */
+
+static short current_surfaces;
+static short paraxial;
+
+static double clear_aperture;
+
+static double aberr_lspher;
+static double aberr_osc;
+static double aberr_lchrom;
+
+static double max_lspher;
+static double max_osc;
+static double max_lchrom;
+
+static double radius_of_curvature;
+static double object_distance;
+static double ray_height;
+static double axis_slope_angle;
+static double from_index;
+static double to_index;
+
+static double spectral_line[9];
+static double s[max_surfaces][5];
+static double od_sa[2][2];
+
+static char outarr[8][80]; /* Computed output of program goes here */
+
+int itercount; /* The iteration counter for the main loop
+ in the program is made global so that
+ the compiler should not be allowed to
+ optimise out the loop over the ray
+ tracing code. */
+
+#ifndef ITERATIONS
+#define ITERATIONS 1000
+#endif
+int niter = ITERATIONS; /* Iteration counter */
+
+static char *refarr[] = { /* Reference results. These happen to
+ be derived from a run on Microsoft
+ Quick BASIC on the IBM PC/AT. */
+
+ " Marginal ray 47.09479120920 0.04178472683",
+ " Paraxial ray 47.08372160249 0.04177864821",
+ "Longitudinal spherical aberration: -0.01106960671",
+ " (Maximum permissible): 0.05306749907",
+ "Offense against sine condition (coma): 0.00008954761",
+ " (Maximum permissible): 0.00250000000",
+ "Axial chromatic aberration: 0.00448229032",
+ " (Maximum permissible): 0.05306749907"
+};
+
+/* The test case used in this program is the design for a 4 inch
+ achromatic telescope objective used as the example in Wyld's
+ classic work on ray tracing by hand, given in Amateur Telescope
+ Making, Volume 3. */
+
+static double testcase[4][4] = {
+ {27.05, 1.5137, 63.6, 0.52},
+ {-16.68, 1, 0, 0.138},
+ {-16.68, 1.6164, 36.7, 0.38},
+ {-78.1, 1, 0, 0}
+};
+
+/* Internal trig functions (used only if INTRIG is defined). These
+ standard functions may be enabled to obtain timings that reflect
+ the machine's floating point performance rather than the speed of
+ its trig function evaluation. */
+
+#ifdef INTRIG
+
+/* The following definitions should keep you from getting intro trouble
+ with compilers which don't let you redefine intrinsic functions. */
+
+#define sin I_sin
+#define cos I_cos
+#define tan I_tan
+#define sqrt I_sqrt
+#define atan I_atan
+#define atan2 I_atan2
+#define asin I_asin
+
+#define fabs(x) ((x < 0.0) ? -x : x)
+
+#define pic 3.1415926535897932
+
+/* Commonly used constants */
+
+static double pi = pic,
+ twopi =pic * 2.0,
+ piover4 = pic / 4.0,
+ fouroverpi = 4.0 / pic,
+ piover2 = pic / 2.0;
+
+/* Coefficients for ATAN evaluation */
+
+static double atanc[] = {
+ 0.0,
+ 0.4636476090008061165,
+ 0.7853981633974483094,
+ 0.98279372324732906714,
+ 1.1071487177940905022,
+ 1.1902899496825317322,
+ 1.2490457723982544262,
+ 1.2924966677897852673,
+ 1.3258176636680324644
+};
+
+/* aint(x) Return integer part of number. Truncates towards 0 */
+
+static double aint(double x)
+{
+ long l;
+
+ /* Note that this routine cannot handle the full floating point
+ number range. This function should be in the machine-dependent
+ floating point library! */
+
+ l = x;
+ if ((int)(-0.5) != 0 && l < 0 )
+ l++;
+ x = l;
+ return x;
+}
+
+/* sin(x) Return sine, x in radians */
+
+static double sin(double x)
+{
+ int sign;
+ double y, r, z;
+
+ x = (((sign= (x < 0.0)) != 0) ? -x: x);
+
+ if (x > twopi)
+ x -= (aint(x / twopi) * twopi);
+
+ if (x > pi) {
+ x -= pi;
+ sign = !sign;
+ }
+
+ if (x > piover2)
+ x = pi - x;
+
+ if (x < piover4) {
+ y = x * fouroverpi;
+ z = y * y;
+ r = y * (((((((-0.202253129293E-13 * z + 0.69481520350522E-11) * z -
+ 0.17572474176170806E-8) * z + 0.313361688917325348E-6) * z -
+ 0.365762041821464001E-4) * z + 0.249039457019271628E-2) * z -
+ 0.0807455121882807815) * z + 0.785398163397448310);
+ } else {
+ y = (piover2 - x) * fouroverpi;
+ z = y * y;
+ r = ((((((-0.38577620372E-12 * z + 0.11500497024263E-9) * z -
+ 0.2461136382637005E-7) * z + 0.359086044588581953E-5) * z -
+ 0.325991886926687550E-3) * z + 0.0158543442438154109) * z -
+ 0.308425137534042452) * z + 1.0;
+ }
+ return sign ? -r : r;
+}
+
+/* cos(x) Return cosine, x in radians, by identity */
+
+static double cos(double x)
+{
+ x = (x < 0.0) ? -x : x;
+ if (x > twopi) /* Do range reduction here to limit */
+ x = x - (aint(x / twopi) * twopi); /* roundoff on add of PI/2 */
+ return sin(x + piover2);
+}
+
+/* tan(x) Return tangent, x in radians, by identity */
+
+static double tan(double x)
+{
+ return sin(x) / cos(x);
+}
+
+/* sqrt(x) Return square root. Initial guess, then Newton-
+ Raphson refinement */
+
+double sqrt(double x)
+{
+ double c, cl, y;
+ int n;
+
+ if (x == 0.0)
+ return 0.0;
+
+ if (x < 0.0) {
+ fprintf(stderr,
+ "\nGood work! You tried to take the square root of %g",
+ x);
+ fprintf(stderr,
+ "\nunfortunately, that is too complex for me to handle.\n");
+ exit(1);
+ }
+
+ y = (0.154116 + 1.893872 * x) / (1.0 + 1.047988 * x);
+
+ c = (y - x / y) / 2.0;
+ cl = 0.0;
+ for (n = 50; c != cl && n--;) {
+ y = y - c;
+ cl = c;
+ c = (y - x / y) / 2.0;
+ }
+ return y;
+}
+
+/* atan(x) Return arctangent in radians,
+ range -pi/2 to pi/2 */
+
+static double atan(double x)
+{
+ int sign, l, y;
+ double a, b, z;
+
+ x = (((sign = (x < 0.0)) != 0) ? -x : x);
+ l = 0;
+
+ if (x >= 4.0) {
+ l = -1;
+ x = 1.0 / x;
+ y = 0;
+ goto atl;
+ } else {
+ if (x < 0.25) {
+ y = 0;
+ goto atl;
+ }
+ }
+
+ y = aint(x / 0.5);
+ z = y * 0.5;
+ x = (x - z) / (x * z + 1);
+
+atl:
+ z = x * x;
+ b = ((((893025.0 * z + 49116375.0) * z + 425675250.0) * z +
+ 1277025750.0) * z + 1550674125.0) * z + 654729075.0;
+ a = (((13852575.0 * z + 216602100.0) * z + 891080190.0) * z +
+ 1332431100.0) * z + 654729075.0;
+ a = (a / b) * x + atanc[y];
+ if (l)
+ a=piover2 - a;
+ return sign ? -a : a;
+}
+
+/* atan2(y,x) Return arctangent in radians of y/x,
+ range -pi to pi */
+
+static double atan2(double y, double x)
+{
+ double temp;
+
+ if (x == 0.0) {
+ if (y == 0.0) /* Special case: atan2(0,0) = 0 */
+ return 0.0;
+ else if (y > 0)
+ return piover2;
+ else
+ return -piover2;
+ }
+ temp = atan(y / x);
+ if (x < 0.0) {
+ if (y >= 0.0)
+ temp += pic;
+ else
+ temp -= pic;
+ }
+ return temp;
+}
+
+/* asin(x) Return arcsine in radians of x */
+
+static double asin(double x)
+{
+ if (fabs(x)>1.0) {
+ fprintf(stderr,
+ "\nInverse trig functions lose much of their gloss when");
+ fprintf(stderr,
+ "\ntheir arguments are greater than 1, such as the");
+ fprintf(stderr,
+ "\nvalue %g you passed.\n", x);
+ exit(1);
+ }
+ return atan2(x, sqrt(1 - x * x));
+}
+#endif
+
+/* Calculate passage through surface
+
+ If the variable PARAXIAL is true, the trace through the
+ surface will be done using the paraxial approximations.
+ Otherwise, the normal trigonometric trace will be done.
+
+ This routine takes the following inputs:
+
+ RADIUS_OF_CURVATURE Radius of curvature of surface
+ being crossed. If 0, surface is
+ plane.
+
+ OBJECT_DISTANCE Distance of object focus from
+ lens vertex. If 0, incoming
+ rays are parallel and
+ the following must be specified:
+
+ RAY_HEIGHT Height of ray from axis. Only
+ relevant if OBJECT.DISTANCE == 0
+
+ AXIS_SLOPE_ANGLE Angle incoming ray makes with axis
+ at intercept
+
+ FROM_INDEX Refractive index of medium being left
+
+ TO_INDEX Refractive index of medium being
+ entered.
+
+ The outputs are the following variables:
+
+ OBJECT_DISTANCE Distance from vertex to object focus
+ after refraction.
+
+ AXIS_SLOPE_ANGLE Angle incoming ray makes with axis
+ at intercept after refraction.
+
+*/
+
+static void transit_surface(void) {
+ double iang, /* Incidence angle */
+ rang, /* Refraction angle */
+ iang_sin, /* Incidence angle sin */
+ rang_sin, /* Refraction angle sin */
+ old_axis_slope_angle, sagitta;
+
+ if (paraxial) {
+ if (radius_of_curvature != 0.0) {
+ if (object_distance == 0.0) {
+ axis_slope_angle = 0.0;
+ iang_sin = ray_height / radius_of_curvature;
+ } else
+ iang_sin = ((object_distance -
+ radius_of_curvature) / radius_of_curvature) *
+ axis_slope_angle;
+
+ rang_sin = (from_index / to_index) *
+ iang_sin;
+ old_axis_slope_angle = axis_slope_angle;
+ axis_slope_angle = axis_slope_angle +
+ iang_sin - rang_sin;
+ if (object_distance != 0.0)
+ ray_height = object_distance * old_axis_slope_angle;
+ object_distance = ray_height / axis_slope_angle;
+ return;
+ }
+ object_distance = object_distance * (to_index / from_index);
+ axis_slope_angle = axis_slope_angle * (from_index / to_index);
+ return;
+ }
+
+ if (radius_of_curvature != 0.0) {
+ if (object_distance == 0.0) {
+ axis_slope_angle = 0.0;
+ iang_sin = ray_height / radius_of_curvature;
+ } else {
+ iang_sin = ((object_distance -
+ radius_of_curvature) / radius_of_curvature) *
+ sin(axis_slope_angle);
+ }
+ iang = asin(iang_sin);
+ rang_sin = (from_index / to_index) *
+ iang_sin;
+ old_axis_slope_angle = axis_slope_angle;
+ axis_slope_angle = axis_slope_angle +
+ iang - asin(rang_sin);
+ sagitta = sin((old_axis_slope_angle + iang) / 2.0);
+ sagitta = 2.0 * radius_of_curvature*sagitta*sagitta;
+ object_distance = ((radius_of_curvature * sin(
+ old_axis_slope_angle + iang)) *
+ cot(axis_slope_angle)) + sagitta;
+ return;
+ }
+
+ rang = -asin((from_index / to_index) *
+ sin(axis_slope_angle));
+ object_distance = object_distance * ((to_index *
+ cos(-rang)) / (from_index *
+ cos(axis_slope_angle)));
+ axis_slope_angle = -rang;
+}
+
+/* Perform ray trace in specific spectral line */
+
+static void trace_line(int line, double ray_h)
+{
+ int i;
+
+ object_distance = 0.0;
+ ray_height = ray_h;
+ from_index = 1.0;
+
+ for (i = 1; i <= current_surfaces; i++) {
+ radius_of_curvature = s[i][1];
+ to_index = s[i][2];
+ if (to_index > 1.0)
+ to_index = to_index + ((spectral_line[4] -
+ spectral_line[line]) /
+ (spectral_line[3] - spectral_line[6])) * ((s[i][2] - 1.0) /
+ s[i][3]);
+ transit_surface();
+ from_index = to_index;
+ if (i < current_surfaces)
+ object_distance = object_distance - s[i][4];
+ }
+}
+
+/* Initialise when called the first time */
+
+int main(int argc, char *argv[])
+{
+ int i, j, k, errors;
+ double od_fline, od_cline;
+#ifdef ACCURACY
+ long passes;
+#endif
+ struct timeval begin_tv, end_tv, diff_tv;
+
+ spectral_line[1] = 7621.0; /* A */
+ spectral_line[2] = 6869.955; /* B */
+ spectral_line[3] = 6562.816; /* C */
+ spectral_line[4] = 5895.944; /* D */
+ spectral_line[5] = 5269.557; /* E */
+ spectral_line[6] = 4861.344; /* F */
+ spectral_line[7] = 4340.477; /* G'*/
+ spectral_line[8] = 3968.494; /* H */
+
+ /* Process the number of iterations argument, if one is supplied. */
+
+ if (argc > 1) {
+ niter = atoi(argv[1]);
+ if (*argv[1] == '-' || niter < 1) {
+ printf("This is John Walker's floating point accuracy and\n");
+ printf("performance benchmark program. You call it with\n");
+ printf("\n%s <itercount>\n\n", argv[0]);
+ printf("where <itercount> is the number of iterations\n");
+ printf("to be executed. Archival timings should be made\n");
+ printf("with the iteration count set so that roughly five\n");
+ printf("minutes of execution is timed.\n");
+ exit(0);
+ }
+ }
+
+ /* Load test case into working array */
+
+ clear_aperture = 4.0;
+ current_surfaces = 4;
+ for (i = 0; i < current_surfaces; i++)
+ for (j = 0; j < 4; j++)
+ s[i + 1][j + 1] = testcase[i][j];
+
+#ifdef ACCURACY
+ printf("Beginning execution of floating point accuracy test...\n");
+ passes = 0;
+#else
+/*
+ printf("Ready to begin John Walker's floating point accuracy\n");
+ printf("and performance benchmark. %d iterations will be made.\n\n", niter);
+
+ printf("\nMeasured run time in seconds should be divided by %.f\n", niter / 1000.0);
+ printf("to normalise for reporting results. For archival results,\n");
+ printf("adjust iteration count so the benchmark runs about five minutes.\n\n");
+*/
+ /* now we start. Get the current time */
+ gettimeofday(&begin_tv, NULL);
+#endif
+
+ /* Perform ray trace the specified number of times. */
+
+#ifdef ACCURACY
+ while (TRUE) {
+ passes++;
+ if ((passes % 100L) == 0) {
+ printf("Pass %ld.\n", passes);
+ }
+#else
+ for (itercount = 0; itercount < niter; itercount++) {
+#endif
+
+ for (paraxial = 0; paraxial <= 1; paraxial++) {
+
+ /* Do main trace in D light */
+
+ trace_line(4, clear_aperture / 2.0);
+ od_sa[paraxial][0] = object_distance;
+ od_sa[paraxial][1] = axis_slope_angle;
+ }
+ paraxial = FALSE;
+
+ /* Trace marginal ray in C */
+
+ trace_line(3, clear_aperture / 2.0);
+ od_cline = object_distance;
+
+ /* Trace marginal ray in F */
+
+ trace_line(6, clear_aperture / 2.0);
+ od_fline = object_distance;
+
+ aberr_lspher = od_sa[1][0] - od_sa[0][0];
+ aberr_osc = 1.0 - (od_sa[1][0] * od_sa[1][1]) /
+ (sin(od_sa[0][1]) * od_sa[0][0]);
+ aberr_lchrom = od_fline - od_cline;
+ max_lspher = sin(od_sa[0][1]);
+
+ /* D light */
+
+ max_lspher = 0.0000926 / (max_lspher * max_lspher);
+ max_osc = 0.0025;
+ max_lchrom = max_lspher;
+#ifndef ACCURACY
+ }
+
+ gettimeofday(&end_tv, NULL);
+#endif
+
+ /* Now evaluate the accuracy of the results from the last ray trace */
+
+ sprintf(outarr[0], "%15s %21.11f %14.11f",
+ "Marginal ray", od_sa[0][0], od_sa[0][1]);
+ sprintf(outarr[1], "%15s %21.11f %14.11f",
+ "Paraxial ray", od_sa[1][0], od_sa[1][1]);
+ sprintf(outarr[2],
+ "Longitudinal spherical aberration: %16.11f",
+ aberr_lspher);
+ sprintf(outarr[3],
+ " (Maximum permissible): %16.11f",
+ max_lspher);
+ sprintf(outarr[4],
+ "Offense against sine condition (coma): %16.11f",
+ aberr_osc);
+ sprintf(outarr[5],
+ " (Maximum permissible): %16.11f",
+ max_osc);
+ sprintf(outarr[6],
+ "Axial chromatic aberration: %16.11f",
+ aberr_lchrom);
+ sprintf(outarr[7],
+ " (Maximum permissible): %16.11f",
+ max_lchrom);
+
+ /* Now compare the edited results with the master values from
+ reference executions of this program. */
+
+ errors = 0;
+ for (i = 0; i < 8; i++) {
+ if (strcmp(outarr[i], refarr[i]) != 0) {
+#ifdef ACCURACY
+ printf("\nError in pass %ld for results on line %d...\n",
+ passes, i + 1);
+#else
+ printf("\nError in results on line %d...\n", i + 1);
+#endif
+ printf("Expected: \"%s\"\n", refarr[i]);
+ printf("Received: \"%s\"\n", outarr[i]);
+ printf("(Errors) ");
+ k = strlen(refarr[i]);
+ for (j = 0; j < k; j++) {
+ printf("%c", refarr[i][j] == outarr[i][j] ? ' ' : '^');
+ if (refarr[i][j] != outarr[i][j])
+ errors++;
+ }
+ printf("\n");
+ }
+ }
+#ifdef ACCURACY
+ }
+#else
+ if (errors > 0) {
+ fprintf(stderr, "\n%d error%s in results. This is VERY SERIOUS.\n",
+ errors, errors > 1 ? "s" : "");
+ return 1;
+ }
+#endif
+ timersub(&end_tv, &begin_tv, &diff_tv);
+
+ printf("Time(s): %u.%u\n", diff_tv.tv_sec, diff_tv.tv_usec);
+
+ return 0;
+}
diff --git a/src/memxfer5b.c b/src/memxfer5b.c
new file mode 100644
index 0000000..179b2d4
--- /dev/null
+++ b/src/memxfer5b.c
@@ -0,0 +1,336 @@
+/* Memory streaming benchmark */
+
+/*
+ * Copyright (C) 2003-2006 IBM
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define __int64 long long
+#include <sys/time.h>
+#define SLASHC '/'
+#define SLASHSTR "/"
+#include <sys/types.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <gettext.h>
+
+#define equal !strcmp
+
+size_t atoik(char *);
+void *Malloc(size_t sz);
+void tstart(void);
+void tend(void);
+double tval(void);
+
+char *methods[] = {
+ "\"memcpy\"",
+ "\"char *\"",
+ "\"short *\"",
+ "\"int *\"",
+ "\"long *\"",
+ "\"__int64 *\"",
+ "\"double *\"",
+};
+int nmethods = sizeof(methods)/sizeof(methods[0]);
+
+int fflag = 0; // if 0, then just Malloc once; else malloc/free each time
+int wflag = 0; // if 1, call SetProcessWorkingSetSize() (WINDOWS ONLY)
+int sflag = 0; // if 1, only print averages.
+int pflag = 0;
+int csvflag = 0; // Print Comma separated list for spreadsheet input.
+char *progname;
+
+double tottim = 0.0;
+
+int main(int ac, char *av[])
+{
+ size_t size;
+ int i;
+ unsigned ui;
+ size_t j;
+ unsigned cnt;
+ int method = 0;
+ char *p1, *p2;
+ char *p,*q;
+ short *sp, *sq;
+ int *ip, *iq;
+ long *lp, *lq;
+ __int64 *llp, *llq;
+ double *dp, *dq;
+ double t;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+#endif
+
+ progname = av[0];
+ if(strrchr(progname,SLASHC))
+ progname = strrchr(progname,SLASHC) + 1;
+
+ while(ac > 1) {
+ if(equal(av[1], "-f")) {
+ ac--;
+ fflag = 1;
+ av++;
+ }
+ else if(equal(av[1], "-w")) {
+ ac--;
+ wflag = 1;
+ av++;
+ }
+ else if(equal(av[1], "-s")) {
+ ac--;
+ sflag = 1;
+ av++;
+ }
+ else if(equal(av[1], "-p")) {
+ ac--;
+ pflag = 1;
+ av++;
+ }
+ else if(equal(av[1], "-csv")) {
+ ac--;
+ csvflag++;
+ av++;
+ }
+ else
+ break;
+ }
+ if(ac < 3) {
+ (void)printf(_("Usage: %s [-f] [-w] [-s] [-p] size cnt [method]\n"),progname);
+ (void)printf(_("\t-f flag says to malloc and free of the \"cnt\" times.\n"));
+ (void)printf(_("\t-w = set process min and max working set size to \"size\"\n"));
+ (void)printf(_("\t-s = silent; only print averages\n"));
+ (void)printf(_("\t-p = prep; \"freshen\" cache before; -w disables\n"));
+ (void)printf(_("\t-csv = print output in CSV format\n"));
+
+ (void)printf(_("\tmethods:\n"));
+ for(i = 0; i < nmethods; i++)
+ printf("\t%2d:\t%s\n",i,methods[i]);
+ return 0;
+ }
+
+ size = atoik(av[1]);
+
+ //
+ // Round size up to 4*sizeof(double) bytes.
+ //
+ if(size != ((size/ (4*sizeof(double)) ) * (4*sizeof(double)) )) {
+ size += (4*sizeof(double));
+ size /= (4*sizeof(double));
+ size *= (4*sizeof(double));
+ }
+ cnt = (unsigned)atoik(av[2]);
+
+ if(fflag == 0) {
+ p1 = (char *)Malloc(size);
+ p2 = (char *)Malloc(size);
+ if(pflag)
+ memcpy(p1,p2,size);
+ }
+
+#if 0
+ /* disable this output as it confuses our automated detection */
+ printf("%s ",progname);
+ if(fflag) printf("-f ");
+ if(wflag) printf("-w ");
+ if(sflag) printf("-s ");
+ if(pflag) printf("-p ");
+ if(csvflag) printf("-csv ");
+ printf("%u %u ", size, cnt);
+ if(csvflag) {
+ printf("Linux");
+ }
+ printf("\n");
+#endif
+
+ if(ac == 3) {
+ ac = 4;
+ av[3] = "0";
+ }
+
+ for(; ac > 3; ac--, av++) {
+ if(isdigit(*av[3])) method = *av[3] - '0';
+ if(method < 0 || method >= nmethods)
+ method = 0;
+ if(sflag)
+ tstart();
+ for(ui = 0; ui < cnt; ui++) {
+ if(!sflag) {
+ (void)printf("%s %d %d %-18.18s\t",
+ progname, size, cnt, methods[method]);
+ tstart();
+ }
+ if(fflag == 1) {
+ p1 = (char *)Malloc(size);
+ p2 = (char *)Malloc(size);
+ }
+ switch(method) {
+ case 0:
+ (void)memcpy(p1, p2, size);
+ break;
+ case 1:
+ p = p1;
+ q = p2;
+ for(j = 0; j < size; j++)
+ *p++ = *q++;
+ break;
+ case 2:
+ sp = (short *)p1;
+ sq = (short *)p2;
+ for(j = 0; j < size; j += sizeof(short))
+ *sp++ = *sq++;
+ break;
+ case 3:
+ ip = (int *)p1;
+ iq = (int *)p2;
+ for(j = 0; j < size; j += sizeof(int))
+ *ip++ = *iq++;
+ break;
+ case 4:
+ lp = (long *)p1;
+ lq = (long *)p2;
+ for(j = 0; j < size; j += sizeof(long))
+ *lp++ = *lq++;
+ break;
+ case 5:
+ llp = (__int64 *)p1;
+ llq = (__int64 *)p2;
+ for(j = 0; j < size; j += sizeof(__int64))
+ *llp++ = *llq++;
+ break;
+ case 6:
+ dp = (double *)p1;
+ dq = (double *)p2;
+ for(j = 0; j < size; j += 4*sizeof(double)) {
+ *dp++ = *dq++;
+ *dp++ = *dq++;
+ *dp++ = *dq++;
+ *dp++ = *dq++;
+ }
+ break;
+
+ }
+ if(fflag == 1) {
+ free(p1);
+ free(p2);
+ }
+ if(!sflag) {
+ tend();
+ t = tval();
+ tottim += t;
+ if(t == 0.0)
+ t = .0001;
+ printf(_(" %8.6f seconds %8.3f MB/s\n"),
+ t,
+ (double)size/t/1000000.);
+ }
+ }
+ if(sflag) {
+ tend();
+ tottim = tval();
+ }
+ if(csvflag) {
+ printf("%s,%u,%u,%8.3f,%8.3f\n",
+ methods[method],size,size*cnt,tottim,(double)size/(tottim/cnt)/1000000.);
+ }
+ else {
+ (void)printf(_("\tAVG: %d %-18.18s\t"), size, methods[method]);
+ (void)printf(" %8.3f MB/s\n", (double)size/(tottim/cnt)/1000000.);
+ }
+ tottim = 0.0;
+ }
+ return 0;
+}
+
+
+size_t atoik(char *s)
+{
+ size_t ret = 0;
+ size_t base;
+
+ if(*s == '0') {
+ base = 8;
+ if(*++s == 'x' || *s == 'X') {
+ base = 16;
+ s++;
+ }
+ }
+ else
+ base = 10;
+
+ for(; isxdigit(*s); s++) {
+ if(base == 16)
+ if(isalpha(*s))
+ ret = base*ret + (toupper(*s) - 'A');
+ else
+ ret = base*ret + (*s - '0');
+ else if(isdigit(*s))
+ ret = base*ret + (*s - '0');
+ else
+ break;
+ }
+ for(; isalpha(*s); s++) {
+ switch(toupper(*s)) {
+ case 'K': ret *= 1024; break;
+ case 'M': ret *= 1024*1024; break;
+ default:
+ return ret;
+ }
+ }
+ return ret;
+}
+void *Malloc(size_t sz)
+{
+ char *p;
+
+ p = (char *)malloc(sz);
+ if(p == NULL) {
+ (void)printf(_("malloc(%d) failed\n"),sz);
+ exit(1);
+ }
+ return (void *)p;
+}
+
+static struct timeval _tstart, _tend;
+
+void tstart(void)
+{
+ gettimeofday(&_tstart, NULL);
+}
+void tend(void)
+{
+ gettimeofday(&_tend, NULL);
+}
+
+double tval()
+{
+ double t1, t2;
+
+ t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000);
+ t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000);
+ return t2-t1;
+}
diff --git a/src/pi8.c b/src/pi8.c
new file mode 100644
index 0000000..b26ed6f
--- /dev/null
+++ b/src/pi8.c
@@ -0,0 +1,316 @@
+/* +++Date last modified: 01-Oct-1996 */
+
+/*
+ pi8.c Sept 9, 1996.
+
+ This program is placed into the public domain by its author,
+ Carey Bloodworth.
+
+ This pi program can calculate pi with either integers, or doubles.
+ It can also use a variety of formulas.
+
+ This code isn't really optimized because it has to work with both the
+ long integer version and the double version, and several formulas.
+ Compromises had to be made in several places.
+
+ When compiling, you can chose to use the FPU or the integer version.
+ By default, it will chose to work only in integers. If you want to
+ use the FPU, compile with additional flag -DUSEFPU
+
+ You have a choice of formulas. By default, it will use the Machin
+ formula of: pi=16arctan(1/5)-4arctan(1/239)
+
+ You could chose to use one of the other formulas.
+
+ for pi=8arctan(1/3)+4arctan(1/7)
+#define ARC3 1
+ for pi=12arctan(1/4)+4arctan(1/20)+4arctan(1/1985)
+#define ARC4 1
+ for pi=16arctan(1/5)-4arctan(1/70)+4arctan(1/99)
+#define ARC5 1
+ for pi=32arctan(1/10)-4arctan(1/239)-16arctan(1/515)
+#define ARC10 1
+
+ Or, of course, you could define it on the compile command line with
+ the -D switch.
+
+ Timings were done on a Cyrix 486/66, with the slow Turbo C++ v3.0
+ 1,000 2,000 3,000 4,000 1,000F 2,000F 3,000F 4,000F
+ Machin 4 18 45 86 1 5 11 20
+ Arc3 6 29 74 140 2 9 20 35
+ Arc4 5 24 64 116 2 7 16 29
+ Arc5 6 26 65 123 1 6 15 26
+ Arc10 4 19 46 86 1 5 11 19
+
+ All of the combinations above were verified to their indicated
+ precision and in each case, only the last few digits were wrong,
+ which is a normal round off / truncation error.
+
+ Better compilers will of course result in faster computations,
+ but the ratios should be the same. When I used GCC 2.6.3 for
+ DOS, I computed 4,000 digits with with the Machin formula and
+ the FPU in 8 seconds. The integer version took 17 seconds.
+
+ I also used the FPU GCC version to compute 65,536 digits of
+ pi and verified them against the Gutenberg PIMIL10.TXT, and
+ only the last 4 digits were incorrect. The computations took
+ 33 minutes and 54 seconds.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#define SHOWTIME
+
+#define DEFAULT_DIGIT_COUNT 2000
+
+#if defined USEFPU
+
+#define BASE 1000000000L
+#define BASEDIGITS 9
+
+typedef long int SHORT;
+typedef double LONG;
+#else
+
+#define BASE 100
+#define BASEDIGITS 2
+
+typedef unsigned char SHORT;
+typedef long int LONG;
+#endif
+
+typedef long int INDEXER;
+
+
+SHORT *pi, *powers, *term;
+INDEXER size = DEFAULT_DIGIT_COUNT;
+
+
+void OutDig(int dig)
+{
+ static int printed = 0;
+
+ putchar(dig + '0');
+ printed++;
+ if ((printed%1000) == 0)
+ {
+ printed = 0;
+ printf("\n\n\n");
+ }
+ if ((printed%50) == 0)
+ printf("\n");
+ else if ((printed%10) == 0)
+ putchar(' ');
+}
+
+
+void PrintShort(SHORT num)
+{
+ int x;
+ int digits[BASEDIGITS + 1];
+
+ for (x = 0; x < BASEDIGITS; x++)
+ {
+ digits[x] = num % 10;
+ num /= 10;
+ }
+ for (x = BASEDIGITS - 1; x >= 0; x--)
+ OutDig(digits[x]);
+}
+
+void Print(SHORT *num)
+{
+ INDEXER x;
+
+ printf("\nPI = 3.\n");
+ for (x = 1; x < size; x++)
+ PrintShort(num[x]);
+ printf("\n");
+}
+
+void arctan(int multiplier, int denom, int sign)
+{
+ INDEXER x;
+ LONG remain, temp, divisor, denom2;
+ SHORT NotZero = 1;
+ INDEXER adv;
+
+ for (x = 0; x < size; x++)
+ powers[x] = 0;
+
+ divisor = 1;
+ denom2 = (LONG)denom;denom2 *= denom2;
+ adv = 0;
+
+ remain = (LONG)multiplier * denom;
+ while (NotZero)
+ {
+ for (x = adv; x < size; x++)
+ {
+ temp = (LONG)powers[x] + remain;
+ powers[x] = (SHORT)(temp / denom2);
+ remain = (temp - (denom2 * (LONG)powers[x])) * BASE;
+ }
+
+ remain = 0;
+ for (x = adv; x < size; x++)
+ {
+ temp = (LONG)powers[x] + remain;
+ term[x] = (SHORT)(temp / divisor);
+ remain = (temp - (divisor * (LONG)term[x])) * BASE;
+ }
+ remain = 0;
+
+ if (sign > 0)
+ {
+ LONG carry, sum;
+
+ carry = 0;
+ for (x = size - 1; x >=0; x--)
+ {
+ sum = (LONG)pi[x] + (LONG)term[x] + carry;
+ carry = 0;
+ if (sum >= BASE)
+ {
+ carry = 1;
+ sum -= BASE;
+ }
+ pi[x] = (SHORT)sum;
+ }
+ }
+ else
+ {
+ LONG borrow, sum;
+
+ borrow = 0;
+ for (x = size - 1; x >= 0; x--)
+ {
+ sum = (LONG)pi[x] - (LONG)term[x] - borrow;
+ borrow = 0;
+ if (sum < 0)
+ {
+ borrow = 1;
+ sum += BASE;
+ }
+ pi[x] = (SHORT)sum;
+ }
+ }
+
+ sign = -sign;
+ divisor += 2;
+ NotZero = 0;
+ for (x = adv; x < size; x++)
+ {
+ if (powers[x])
+ {
+ NotZero = 1;
+ break;
+ }
+ }
+
+ if (NotZero)
+ {
+ while (powers[adv] == 0)
+ adv++;
+ }
+ /* We can skip ones that are already 0 */
+ }
+}
+
+static void usage(const char *prg, FILE *out)
+{
+ fprintf(out, "usage: %s [options]\n", prg);
+ fprintf(out, " options are:\n");
+ fprintf(out, " '-c count' digits to compute. Default is %ld, should not be 0.\n", size);
+ fprintf(out, " '-q' be quiet, do not emit pi\n");
+ fprintf(out, " '-v' print program version and exit\n");
+ fprintf(out, " '-h' print this help and exit\n");
+}
+
+int main(int argc, char *argv[])
+{
+ INDEXER x;
+ int quiet = 0, c;
+ struct timeval start, stop, diff;
+
+ /* handle command line options first */
+ while (1) {
+ c = getopt(argc, argv, "c:qhv");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'c':
+ size = atoi(optarg); /* digits to compute */
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'h':
+ usage(argv[0], stdout);
+ exit(EXIT_SUCCESS);
+ case 'v':
+ printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (! size) {
+ usage(argv[0], stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ size = ((size + BASEDIGITS - 1) / BASEDIGITS) + 1;
+
+ pi = malloc(sizeof(SHORT) * size);
+ powers = malloc(sizeof(SHORT) * size);
+ term = malloc(sizeof(SHORT) * size);
+
+ if ((pi == NULL) || (powers == NULL) || (term == NULL)) {
+ fprintf(stderr, "Unable to allocate enough memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (x = 0; x < size; x++)
+ pi[x] = 0;
+
+ gettimeofday(&start, NULL);
+
+#if defined ARC3
+ arctan(8, 3, 1);
+ arctan(4, 7, 1);
+#elif defined ARC5
+ arctan(16, 5, 1);
+ arctan(4, 70, -1);
+ arctan(4, 99, 1);
+#elif defined ARC4
+ arctan(12, 4, 1);
+ arctan(4, 20, 1);
+ arctan(4, 1985, 1);
+#elif defined ARC10
+ arctan(32, 10, 1);
+ arctan(4, 239, -1);
+ arctan(16, 515, -1);
+#else
+ /* Machin formula */
+ arctan(16, 5, 1);
+ arctan(4, 239, -1);
+#endif
+
+ gettimeofday(&stop, NULL);
+ if (!quiet)
+ Print(pi);
+
+ timersub(&stop, &start, &diff);
+ printf("\nTime (s): %ld.%ld\n", diff.tv_sec, diff.tv_usec);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/timeout.c b/src/timeout.c
new file mode 100644
index 0000000..7b784c5
--- /dev/null
+++ b/src/timeout.c
@@ -0,0 +1,188 @@
+/*
+ *LICENSE
+ * The IBM PUBLIC LICENSE must be distributed with this
+ * software.
+ * HISTORY
+ * This program was first released as part of SATAN.
+ * AUTHOR(S)
+ * Wietse Venema
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* System libraries. */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <pthread.h>
+#include <string.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+static int kill_signal = SIGKILL;
+static const char *commandname;
+/* the child we control */
+static pid_t child_pid;
+
+static void usage(const char *prg, FILE *out)
+{
+ fprintf(out, "usage: %s [options] -t time \"command...\"\n", prg);
+ fprintf(out, " 'time' in seconds (default), or seconds/minutes/hours/days with the extensions 's|m|h|d'\n");
+ fprintf(out, " options are:\n");
+ fprintf(out, " '-s signal' to send to the controlled application when the timeout is reached\n");
+ fprintf(out, " - default is SIGKILL\n");
+ fprintf(out, " '-v' print program version and exit\n");
+ fprintf(out, " '-h' print this help and exit\n");
+}
+
+/*
+ * kill all children in the case we are receiving a signal
+ */
+static void terminate(int sig)
+{
+ signal(kill_signal, SIG_DFL); /* maybe 'sig' instead of 'kill_signal' ? */
+ /* kill the whole process group */
+ kill(-child_pid, kill_signal);
+}
+
+int main(int argc, char *argv[])
+{
+ int time_to_run = -1, status, current_sched, c;
+ pid_t pid;
+ struct sched_param schedp;
+ char modifier = 's'; /* seconds are the default */
+
+ if (argc == 1) {
+ usage(argv[0], stderr);
+ exit(1);
+ }
+
+ /* handle command line options first */
+ while (1) {
+ c = getopt(argc, argv, "s:t:hv");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 't':
+ status = sscanf(optarg, "%d%c", &time_to_run, &modifier);
+ if (status == 0) {
+ fprintf(stderr, "Error: Need proper time input.\n");
+ usage(argv[0], stderr);
+ exit(1);
+ }
+ switch (modifier) {
+ case 's':
+ break; /* use value as given */
+ case 'm':
+ time_to_run *= 60;
+ break;
+ case 'h':
+ time_to_run *= (60 * 60);
+ break;
+ case 'd':
+ time_to_run *= (60 * 60 * 24);
+ break;
+ default:
+ fprintf(stderr, "Invalid time modifier, try: s|m|h|d\n");
+ exit(1);
+ }
+ break;
+ case 's':
+ kill_signal = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0], stdout);
+ exit(0);
+ case 'v':
+ printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ exit(0);
+ }
+ }
+
+ if (optind < argc)
+ commandname = argv[optind];
+
+ if (time_to_run == -1) {
+ fprintf(stderr, "No timeout value given\n");
+ usage(argv[0], stderr);
+ exit(1);
+ }
+
+ current_sched = sched_getscheduler(0);
+ /*
+ * To avoid a race, we rise our priority *right now*.
+ * Omit error handling. This program will be run as root.
+ */
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = sched_get_priority_max(SCHED_FIFO); /* highest! */
+ sched_setscheduler(0, SCHED_FIFO, &schedp);
+
+ switch (child_pid = fork()) {
+ case -1: /* error */
+ perror("timeout: fork");
+ exit(50);
+
+ case 00: /* run controlled command */
+ /*
+ * Lower priority to a regular value
+ */
+ memset(&schedp, 0, sizeof(schedp));
+ schedp.sched_priority = sched_get_priority_min(current_sched); /* standard */
+ sched_setscheduler(0, current_sched, &schedp);
+ /*
+ * Become a separate process group leader. This will ensure
+ * the parent can kill all members of this process group
+ * and not itself by accident.
+ */
+ pid = setsid(); /* we are now the leader of a process group */
+ if (pid == (pid_t)-1)
+ perror("Becoming group leader");
+
+ execvp(argv[optind], &argv[optind]);
+ perror(commandname);
+ exit(60);
+
+ default: /* become watchdog */
+ /*
+ * we now should be the process with the strongest
+ * priority in the system. Lets keep an eye on our
+ * child
+ */
+ (void) signal(SIGHUP, terminate);
+ (void) signal(SIGINT, terminate);
+ (void) signal(SIGQUIT, terminate);
+ (void) signal(SIGTERM, terminate);
+ (void) signal(SIGALRM, terminate);
+ alarm(time_to_run);
+ /*
+ * Wait until our child terminates
+ */
+ while ((pid = wait(&status)) != -1 && pid != child_pid)
+ /* void */ ;
+
+ if (pid != child_pid)
+ return 70; /* something really strange happens */
+
+ if (WIFEXITED(status)) {
+ /*
+ * Does our child finds a regular end?
+ */
+ return WEXITSTATUS(status); /* return its value */
+ }
+
+ if (WIFSIGNALED(status)) {
+ /*
+ * Terminated by a signal?
+ */
+ return 80 + WTERMSIG(status);
+ }
+ }
+
+ return 71; /* other strange things are happened */
+}
diff --git a/wizzard.sh b/wizzard.sh
new file mode 100755
index 0000000..a6862bd
--- /dev/null
+++ b/wizzard.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+if [ -f wizzard.sh ]; then
+ echo "error: run wizzard.sh from the directory you want to autotoolize"
+ exit 1
+fi
+
+SKELDIR=$(cd $(dirname $0) && pwd)
+HERE=$(pwd)
+echo -n "project name: "
+read NAME
+NAME_UP=$(echo $NAME | tr '[a-z]' '[A-Z]')
+
+tar -C "${SKELDIR}" -c . --exclude .svn | tar -C "${HERE}" -xf -
+
+mv "config/@name@.pc.in" "config/${NAME}.pc.in"
+mv "src/lib@name@.c" "src/lib${NAME}.c"
+mv "src/@name@.c" "src/${NAME}.c"
+mv "include/@name@.h" "include/${NAME}.h"
+mv "include/@name@stuff.h" "include/${NAME}stuff.h"
+
+for i in \
+ configure.ac \
+ config/GNUmakefile.am \
+ config/${NAME}.pc.in \
+ include/GNUmakefile.am \
+ src/GNUmakefile.am \
+ tests/GNUmakefile.am \
+ include/${NAME}.h \
+ include/${NAME}stuff.h \
+; do
+ sed -i -e "s/\@name\@/${NAME}/g" $i
+ sed -i -e "s/\@NAME\@/${NAME_UP}/g" $i
+done
+